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/html/HTMLFrameElement.h"
56 #include "core/frame/Frame.h"
57 #include "core/frame/FrameView.h"
58 #include "core/page/Page.h"
59 #include "core/frame/Settings.h"
60 #include "core/frame/animation/AnimationController.h"
61 #include "core/page/scrolling/ScrollingCoordinator.h"
62 #include "core/rendering/ColumnInfo.h"
63 #include "core/rendering/CompositedLayerMapping.h"
64 #include "core/rendering/FilterEffectRenderer.h"
65 #include "core/rendering/HitTestRequest.h"
66 #include "core/rendering/HitTestResult.h"
67 #include "core/rendering/HitTestingTransformState.h"
68 #include "core/rendering/RenderFlowThread.h"
69 #include "core/rendering/RenderGeometryMap.h"
70 #include "core/rendering/RenderInline.h"
71 #include "core/rendering/RenderLayerCompositor.h"
72 #include "core/rendering/RenderReplica.h"
73 #include "core/rendering/RenderScrollbar.h"
74 #include "core/rendering/RenderScrollbarPart.h"
75 #include "core/rendering/RenderTreeAsText.h"
76 #include "core/rendering/RenderView.h"
77 #include "core/rendering/svg/ReferenceFilterBuilder.h"
78 #include "core/rendering/svg/RenderSVGResourceClipper.h"
79 #include "platform/LengthFunctions.h"
80 #include "platform/Partitions.h"
81 #include "platform/TraceEvent.h"
82 #include "platform/geometry/FloatPoint3D.h"
83 #include "platform/geometry/FloatRect.h"
84 #include "platform/graphics/GraphicsContextStateSaver.h"
85 #include "platform/graphics/filters/ReferenceFilter.h"
86 #include "platform/graphics/filters/SourceGraphic.h"
87 #include "platform/transforms/ScaleTransformOperation.h"
88 #include "platform/transforms/TransformationMatrix.h"
89 #include "platform/transforms/TranslateTransformOperation.h"
90 #include "public/platform/Platform.h"
91 #include "wtf/StdLibExtras.h"
92 #include "wtf/text/CString.h"
98 using namespace HTMLNames;
100 RenderLayer::RenderLayer(RenderLayerModelObject* renderer, LayerType type)
101 : m_isOverflowOnlyLayer(type == OverflowClipLayer)
102 , m_hasSelfPaintingLayerDescendant(false)
103 , m_hasSelfPaintingLayerDescendantDirty(false)
104 , m_hasOutOfFlowPositionedDescendant(false)
105 , m_hasOutOfFlowPositionedDescendantDirty(true)
106 , m_hasUnclippedDescendant(false)
107 , m_isUnclippedDescendant(false)
108 , m_isRootLayer(renderer->isRenderView())
109 , m_usedTransparency(false)
110 , m_visibleContentStatusDirty(true)
111 , m_hasVisibleContent(false)
112 , m_visibleDescendantStatusDirty(false)
113 , m_hasVisibleDescendant(false)
114 , m_hasVisibleNonLayerContent(false)
115 , m_isPaginated(false)
116 , m_3DTransformedDescendantStatusDirty(true)
117 , m_has3DTransformedDescendant(false)
118 , m_containsDirtyOverlayScrollbars(false)
119 , m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell())
120 , m_hasFilterInfo(false)
121 , m_renderer(renderer)
127 , m_staticInlinePosition(0)
128 , m_staticBlockPosition(0)
129 , m_enclosingPaginationLayer(0)
130 , m_groupedMapping(0)
131 , m_repainter(renderer)
132 , m_clipper(renderer)
133 , m_blendInfo(renderer)
135 updateStackingNode();
137 m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
139 if (!renderer->firstChild() && renderer->style()) {
140 m_visibleContentStatusDirty = false;
141 m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
144 updateScrollableArea();
147 RenderLayer::~RenderLayer()
149 if (!m_renderer->documentBeingDestroyed())
150 compositor()->removeOutOfFlowPositionedLayer(this);
152 if (renderer()->frame() && renderer()->frame()->page()) {
153 if (ScrollingCoordinator* scrollingCoordinator = renderer()->frame()->page()->scrollingCoordinator())
154 scrollingCoordinator->willDestroyRenderLayer(this);
157 removeFilterInfoIfNeeded();
159 // Child layers will be deleted by their corresponding render objects, so
160 // we don't need to delete them ourselves.
162 clearCompositedLayerMapping(true);
165 String RenderLayer::debugName() const
168 return m_reflectionInfo->debugName();
169 return renderer()->debugName();
172 RenderLayerCompositor* RenderLayer::compositor() const
174 if (!renderer()->view())
176 return renderer()->view()->compositor();
179 void RenderLayer::contentChanged(ContentChangeType changeType)
181 // This can get called when video becomes accelerated, so the layers may change.
182 if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this))
183 compositor()->setCompositingLayersNeedRebuild();
185 if (m_compositedLayerMapping)
186 m_compositedLayerMapping->contentChanged(changeType);
189 bool RenderLayer::canRender3DTransforms() const
191 return compositor()->canRender3DTransforms();
194 bool RenderLayer::paintsWithFilters() const
196 if (!renderer()->hasFilter())
199 if (compositingState() != PaintsIntoOwnBacking)
202 if (!m_compositedLayerMapping || !m_compositedLayerMapping->canCompositeFilters())
208 bool RenderLayer::requiresFullLayerImageForFilters() const
210 if (!paintsWithFilters())
212 FilterEffectRenderer* filter = filterRenderer();
213 return filter ? filter->hasFilterThatMovesPixels() : false;
216 LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const
218 hasLayerOffset = true;
221 return LayoutPoint();
223 // This is similar to root() but we check if an ancestor layer would
224 // prevent the optimization from working.
225 const RenderLayer* rootLayer = 0;
226 for (const RenderLayer* parentLayer = parent(); parentLayer; rootLayer = parentLayer, parentLayer = parentLayer->parent()) {
227 hasLayerOffset = parentLayer->canUseConvertToLayerCoords();
229 return LayoutPoint();
231 ASSERT(rootLayer == root());
234 parent()->convertToLayerCoords(rootLayer, offset);
238 void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags)
240 TRACE_EVENT0("blink_rendering", "RenderLayer::updateLayerPositionsAfterLayout");
241 RenderGeometryMap geometryMap(UseTransforms);
242 if (this != rootLayer)
243 geometryMap.pushMappingsToAncestor(parent(), 0);
244 updateLayerPositions(&geometryMap, flags);
247 void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLayerPositionsFlags flags)
249 updateLayerPosition(); // For relpositioned layers or non-positioned layers,
250 // we need to keep in sync, since we may have shifted relative
251 // to our parent layer.
253 geometryMap->pushMappingsToAncestor(this, parent());
255 // Clear our cached clip rect information.
256 m_clipper.clearClipRects();
258 if (hasOverflowControls()) {
259 LayoutPoint offsetFromRoot;
261 offsetFromRoot = LayoutPoint(geometryMap->absolutePoint(FloatPoint()));
263 // FIXME: It looks suspicious to call convertToLayerCoords here
264 // as canUseConvertToLayerCoords may be true for an ancestor layer.
265 convertToLayerCoords(root(), offsetFromRoot);
267 scrollableArea()->positionOverflowControls(toIntSize(roundedIntPoint(offsetFromRoot)));
270 updateDescendantDependentFlags();
272 if (flags & UpdatePagination)
275 m_isPaginated = false;
276 m_enclosingPaginationLayer = 0;
279 repainter().repaintAfterLayout(geometryMap, flags & CheckForRepaint);
281 // Go ahead and update the reflection's position and size.
282 if (m_reflectionInfo)
283 m_reflectionInfo->reflection()->layout();
285 // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
286 bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
287 if (hasCompositedLayerMapping())
288 flags &= ~IsCompositingUpdateRoot;
290 if (useRegionBasedColumns() && renderer()->isInFlowRenderFlowThread()) {
292 flags |= UpdatePagination;
295 if (renderer()->hasColumns())
296 flags |= UpdatePagination;
298 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
299 child->updateLayerPositions(geometryMap, flags);
301 if ((flags & UpdateCompositingLayers) && hasCompositedLayerMapping()) {
302 CompositedLayerMapping::UpdateAfterLayoutFlags updateFlags = CompositedLayerMapping::CompositingChildrenOnly;
303 if (flags & NeedsFullRepaintInBacking)
304 updateFlags |= CompositedLayerMapping::NeedsFullRepaint;
306 updateFlags |= CompositedLayerMapping::IsUpdateRoot;
307 compositedLayerMapping()->updateAfterLayout(updateFlags);
311 geometryMap->popMappingsToAncestor(parent());
314 void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant()
316 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
317 if (!layer->m_hasSelfPaintingLayerDescendantDirty && layer->hasSelfPaintingLayerDescendant())
320 layer->m_hasSelfPaintingLayerDescendantDirty = false;
321 layer->m_hasSelfPaintingLayerDescendant = true;
325 void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
327 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
328 layer->m_hasSelfPaintingLayerDescendantDirty = true;
329 // If we have reached a self-painting layer, we know our parent should have a self-painting descendant
330 // in this case, there is no need to dirty our ancestors further.
331 if (layer->isSelfPaintingLayer()) {
332 ASSERT(!parent() || parent()->m_hasSelfPaintingLayerDescendantDirty || parent()->hasSelfPaintingLayerDescendant());
338 void RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant()
340 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
341 if (!layer->m_hasOutOfFlowPositionedDescendantDirty && layer->hasOutOfFlowPositionedDescendant())
344 layer->setHasOutOfFlowPositionedDescendantDirty(false);
345 layer->setHasOutOfFlowPositionedDescendant(true);
349 void RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus()
351 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
352 layer->setHasOutOfFlowPositionedDescendantDirty(true);
354 // We may or may not have an unclipped descendant. If we do, we'll reset
355 // this to true the next time composited scrolling state is updated.
356 layer->setHasUnclippedDescendant(false);
358 // If we have reached an out of flow positioned layer, we know our parent should have an out-of-flow positioned descendant.
359 // In this case, there is no need to dirty our ancestors further.
360 if (layer->renderer()->isOutOfFlowPositioned()) {
361 ASSERT(!parent() || parent()->m_hasOutOfFlowPositionedDescendantDirty || parent()->hasOutOfFlowPositionedDescendant());
367 bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
369 const EPosition position = renderer()->style()->position();
370 const EPosition otherPosition = other->renderer()->style()->position();
371 const RenderObject* containingBlock = renderer()->containingBlock();
372 const RenderObject* otherContainingBlock = other->renderer()->containingBlock();
373 const RenderLayer* rootLayer = renderer()->view()->compositor()->rootRenderLayer();
375 // Fixed-position elements are a special case. They are static with respect
376 // to the viewport, which is not represented by any RenderObject, and their
377 // containingBlock() method returns the root HTML element (while its true
378 // containingBlock should really be the viewport). The real measure for a
379 // non-transformed fixed-position element is as follows: any fixed position
380 // element, A, scrolls with respect an element, B, if and only if B is not
383 // Unfortunately, it gets a bit more complicated - a fixed-position element
384 // which has a transform acts exactly as an absolute-position element
385 // (including having a real, non-viewport containing block).
387 // Below, a "root" fixed position element is defined to be one whose
388 // containing block is the root. These root-fixed-position elements are
389 // the only ones that need this special case code - other fixed position
390 // elements, as well as all absolute, relative, and static elements use the
392 const bool isRootFixedPos = position == FixedPosition && containingBlock->enclosingLayer() == rootLayer;
393 const bool otherIsRootFixedPos = otherPosition == FixedPosition && otherContainingBlock->enclosingLayer() == rootLayer;
395 if (isRootFixedPos && otherIsRootFixedPos)
397 if (isRootFixedPos || otherIsRootFixedPos)
400 if (containingBlock == otherContainingBlock)
403 // Maintain a set of containing blocks between the first layer and its
404 // closest scrollable ancestor.
405 HashSet<const RenderObject*> containingBlocks;
406 while (containingBlock) {
407 if (containingBlock->enclosingLayer()->scrollsOverflow())
409 containingBlocks.add(containingBlock);
410 containingBlock = containingBlock->containingBlock();
413 // Do the same for the 2nd layer, but if we find a common containing block,
414 // it means both layers are contained within a single non-scrolling subtree.
415 // Hence, they will not scroll with respect to each other.
416 while (otherContainingBlock) {
417 if (containingBlocks.contains(otherContainingBlock))
419 if (otherContainingBlock->enclosingLayer()->scrollsOverflow())
421 otherContainingBlock = otherContainingBlock->containingBlock();
427 void RenderLayer::updateLayerPositionsAfterDocumentScroll()
429 ASSERT(this == renderer()->view()->layer());
431 RenderGeometryMap geometryMap(UseTransforms);
432 updateLayerPositionsAfterScroll(&geometryMap);
435 void RenderLayer::updateLayerPositionsAfterOverflowScroll()
437 RenderGeometryMap geometryMap(UseTransforms);
438 RenderView* view = renderer()->view();
439 if (this != view->layer())
440 geometryMap.pushMappingsToAncestor(parent(), 0);
442 // FIXME: why is it OK to not check the ancestors of this layer in order to
443 // initialize the HasSeenViewportConstrainedAncestor and HasSeenAncestorWithOverflowClip flags?
444 updateLayerPositionsAfterScroll(&geometryMap, IsOverflowScroll);
447 void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap, UpdateLayerPositionsAfterScrollFlags flags)
449 // FIXME: This shouldn't be needed, but there are some corner cases where
450 // these flags are still dirty. Update so that the check below is valid.
451 updateDescendantDependentFlags();
453 // If we have no visible content and no visible descendants, there is no point recomputing
454 // our rectangles as they will be empty. If our visibility changes, we are expected to
455 // recompute all our positions anyway.
456 if (subtreeIsInvisible())
459 bool positionChanged = updateLayerPosition();
461 flags |= HasChangedAncestor;
464 geometryMap->pushMappingsToAncestor(this, parent());
466 if (flags & HasChangedAncestor || flags & HasSeenViewportConstrainedAncestor || flags & IsOverflowScroll)
467 m_clipper.clearClipRects();
469 if (renderer()->style()->hasViewportConstrainedPosition())
470 flags |= HasSeenViewportConstrainedAncestor;
472 if (renderer()->hasOverflowClip())
473 flags |= HasSeenAncestorWithOverflowClip;
475 if (flags & HasSeenViewportConstrainedAncestor
476 || (flags & IsOverflowScroll && flags & HasSeenAncestorWithOverflowClip && !m_canSkipRepaintRectsUpdateOnScroll)) {
477 // FIXME: We could track the repaint container as we walk down the tree.
478 repainter().computeRepaintRects(renderer()->containerForRepaint(), geometryMap);
480 // Check that RenderLayerRepainter's cached rects are correct.
481 // FIXME: re-enable these assertions when the issue with table cells is resolved: https://bugs.webkit.org/show_bug.cgi?id=103432
482 // ASSERT(repainter().m_repaintRect == renderer()->clippedOverflowRectForRepaint(renderer()->containerForRepaint()));
483 // ASSERT(repainter().m_outlineBox == renderer()->outlineBoundsForRepaint(renderer()->containerForRepaint(), geometryMap));
486 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
487 child->updateLayerPositionsAfterScroll(geometryMap, flags);
489 // We don't update our reflection as scrolling is a translation which does not change the size()
490 // of an object, thus RenderReplica will still repaint itself properly as the layer position was
494 geometryMap->popMappingsToAncestor(parent());
497 void RenderLayer::updateTransform()
499 // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
500 // so check style too.
501 bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
502 bool had3DTransform = has3DTransform();
504 bool hadTransform = m_transform;
505 if (hasTransform != hadTransform) {
507 m_transform = adoptPtr(new TransformationMatrix);
511 // Layers with transforms act as clip rects roots, so clear the cached clip rects here.
512 m_clipper.clearClipRectsIncludingDescendants();
516 RenderBox* box = renderBox();
518 m_transform->makeIdentity();
519 box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
520 makeMatrixRenderable(*m_transform, canRender3DTransforms());
523 if (had3DTransform != has3DTransform())
524 dirty3DTransformedDescendantStatus();
527 TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const
530 return TransformationMatrix();
532 // FIXME: handle this under web-animations
533 if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled() && renderer()->style()->isRunningAcceleratedAnimation()) {
534 TransformationMatrix currTransform;
535 RefPtr<RenderStyle> style = renderer()->animation().getAnimatedStyleForRenderer(renderer());
536 style->applyTransform(currTransform, renderBox()->pixelSnappedBorderBoxRect().size(), applyOrigin);
537 makeMatrixRenderable(currTransform, canRender3DTransforms());
538 return currTransform;
541 // m_transform includes transform-origin, so we need to recompute the transform here.
542 if (applyOrigin == RenderStyle::ExcludeTransformOrigin) {
543 RenderBox* box = renderBox();
544 TransformationMatrix currTransform;
545 box->style()->applyTransform(currTransform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
546 makeMatrixRenderable(currTransform, canRender3DTransforms());
547 return currTransform;
553 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
556 return TransformationMatrix();
558 if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
559 TransformationMatrix matrix = *m_transform;
560 makeMatrixRenderable(matrix, false /* flatten 3d */);
567 RenderLayer* RenderLayer::enclosingOverflowClipLayer(IncludeSelfOrNot includeSelf) const
569 const RenderLayer* layer = (includeSelf == IncludeSelf) ? this : parent();
571 if (layer->renderer()->hasOverflowClip())
572 return const_cast<RenderLayer*>(layer);
574 layer = layer->parent();
579 static bool checkContainingBlockChainForPagination(RenderLayerModelObject* renderer, RenderBox* ancestorColumnsRenderer)
581 RenderView* view = renderer->view();
582 RenderLayerModelObject* prevBlock = renderer;
583 RenderBlock* containingBlock;
584 for (containingBlock = renderer->containingBlock();
585 containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer;
586 containingBlock = containingBlock->containingBlock())
587 prevBlock = containingBlock;
589 // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
590 if (containingBlock != ancestorColumnsRenderer)
593 // If the previous block is absolutely positioned, then we can't be paginated by the columns block.
594 if (prevBlock->isOutOfFlowPositioned())
597 // Otherwise we are paginated by the columns block.
601 bool RenderLayer::useRegionBasedColumns() const
603 const Settings* settings = renderer()->document().settings();
604 return settings && settings->regionBasedColumnsEnabled();
607 void RenderLayer::updatePagination()
609 m_isPaginated = false;
610 m_enclosingPaginationLayer = 0;
612 if (hasCompositedLayerMapping() || !parent())
613 return; // FIXME: We will have to deal with paginated compositing layers someday.
614 // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though.
616 // The main difference between the paginated booleans for the old column code and the new column code
617 // is that each paginated layer has to paint on its own with the new code. There is no
618 // recurring into child layers. This means that the m_isPaginated bits for the new column code can't just be set on
619 // "roots" that get split and paint all their descendants. Instead each layer has to be checked individually and
620 // genuinely know if it is going to have to split itself up when painting only its contents (and not any other descendant
621 // layers). We track an enclosingPaginationLayer instead of using a simple bit, since we want to be able to get back
622 // to that layer easily.
623 bool regionBasedColumnsUsed = useRegionBasedColumns();
624 if (regionBasedColumnsUsed && renderer()->isInFlowRenderFlowThread()) {
625 m_enclosingPaginationLayer = this;
629 if (m_stackingNode->isNormalFlowOnly()) {
630 if (regionBasedColumnsUsed) {
631 // Content inside a transform is not considered to be paginated, since we simply
632 // paint the transform multiple times in each column, so we don't have to use
633 // fragments for the transformed content.
634 m_enclosingPaginationLayer = parent()->enclosingPaginationLayer();
635 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform())
636 m_enclosingPaginationLayer = 0;
638 m_isPaginated = parent()->renderer()->hasColumns();
642 // For the new columns code, we want to walk up our containing block chain looking for an enclosing layer. Once
643 // we find one, then we just check its pagination status.
644 if (regionBasedColumnsUsed) {
645 RenderView* view = renderer()->view();
646 RenderBlock* containingBlock;
647 for (containingBlock = renderer()->containingBlock();
648 containingBlock && containingBlock != view;
649 containingBlock = containingBlock->containingBlock()) {
650 if (containingBlock->hasLayer()) {
651 // Content inside a transform is not considered to be paginated, since we simply
652 // paint the transform multiple times in each column, so we don't have to use
653 // fragments for the transformed content.
654 m_enclosingPaginationLayer = containingBlock->layer()->enclosingPaginationLayer();
655 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform())
656 m_enclosingPaginationLayer = 0;
663 // If we're not normal flow, then we need to look for a multi-column object between us and our stacking container.
664 RenderLayerStackingNode* ancestorStackingContainerNode = m_stackingNode->ancestorStackingContainerNode();
665 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
666 if (curr->renderer()->hasColumns()) {
667 m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox());
670 if (curr->stackingNode() == ancestorStackingContainerNode)
675 void RenderLayer::setHasVisibleContent()
677 if (m_hasVisibleContent && !m_visibleContentStatusDirty) {
678 ASSERT(!parent() || parent()->hasVisibleDescendant());
682 m_visibleContentStatusDirty = false;
683 m_hasVisibleContent = true;
684 repainter().computeRepaintRects(renderer()->containerForRepaint());
685 if (!m_stackingNode->isNormalFlowOnly()) {
686 // We don't collect invisible layers in z-order lists if we are not in compositing mode.
687 // As we became visible, we need to dirty our stacking containers ancestors to be properly
688 // collected. FIXME: When compositing, we could skip this dirtying phase.
689 for (RenderLayerStackingNode* sc = m_stackingNode->ancestorStackingContainerNode(); sc; sc = sc->ancestorStackingContainerNode()) {
690 sc->dirtyZOrderLists();
691 if (sc->layer()->hasVisibleContent())
697 parent()->setAncestorChainHasVisibleDescendant();
700 void RenderLayer::dirtyVisibleContentStatus()
702 m_visibleContentStatusDirty = true;
704 parent()->dirtyAncestorChainVisibleDescendantStatus();
707 void RenderLayer::dirtyAncestorChainVisibleDescendantStatus()
709 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
710 if (layer->m_visibleDescendantStatusDirty)
713 layer->m_visibleDescendantStatusDirty = true;
717 void RenderLayer::setAncestorChainHasVisibleDescendant()
719 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
720 if (!layer->m_visibleDescendantStatusDirty && layer->hasVisibleDescendant())
723 layer->m_hasVisibleDescendant = true;
724 layer->m_visibleDescendantStatusDirty = false;
728 void RenderLayer::updateHasUnclippedDescendant()
730 TRACE_EVENT0("blink_rendering", "RenderLayer::updateHasUnclippedDescendant");
731 ASSERT(renderer()->isOutOfFlowPositioned());
732 if (!m_hasVisibleContent && !m_hasVisibleDescendant)
735 FrameView* frameView = renderer()->view()->frameView();
739 const RenderObject* containingBlock = renderer()->containingBlock();
740 setIsUnclippedDescendant(false);
741 for (RenderLayer* ancestor = parent(); ancestor && ancestor->renderer() != containingBlock; ancestor = ancestor->parent()) {
742 // TODO(vollick): This isn't quite right. Whenever ancestor is composited and clips
743 // overflow, we're technically unclipped. However, this will currently cause a huge
744 // number of layers to report that they are unclipped. Eventually, when we've formally
745 // separated the clipping, transform, opacity, and stacking trees here and in the
746 // compositor, we will be able to relax this restriction without it being prohibitively
747 // expensive (currently, we have to do a lot of work in the compositor to honor a
748 // clip child/parent relationship).
749 if (ancestor->scrollsOverflow())
750 setIsUnclippedDescendant(true);
751 ancestor->setHasUnclippedDescendant(true);
755 // FIXME: this is quite brute-force. We could be more efficient if we were to
756 // track state and update it as appropriate as changes are made in the RenderObject tree.
757 void RenderLayer::updateHasVisibleNonLayerContent()
759 TRACE_EVENT0("blink_rendering", "RenderLayer::updateHasVisibleNonLayerContent");
760 m_hasVisibleNonLayerContent = false;
761 for (RenderObject* r = renderer()->firstChild(); r; r = r->nextSibling()) {
762 if (!r->hasLayer()) {
763 m_hasVisibleNonLayerContent = true;
769 static bool subtreeContainsOutOfFlowPositionedLayer(const RenderLayer* subtreeRoot)
771 return (subtreeRoot->renderer() && subtreeRoot->renderer()->isOutOfFlowPositioned()) || subtreeRoot->hasOutOfFlowPositionedDescendant();
774 void RenderLayer::updateDescendantDependentFlags()
776 if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty) {
777 m_hasVisibleDescendant = false;
778 m_hasSelfPaintingLayerDescendant = false;
779 m_hasOutOfFlowPositionedDescendant = false;
781 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
782 child->updateDescendantDependentFlags();
784 bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
785 bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
786 bool hasOutOfFlowPositionedDescendant = subtreeContainsOutOfFlowPositionedLayer(child);
788 m_hasVisibleDescendant |= hasVisibleDescendant;
789 m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
790 m_hasOutOfFlowPositionedDescendant |= hasOutOfFlowPositionedDescendant;
792 if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && hasOutOfFlowPositionedDescendant)
796 m_visibleDescendantStatusDirty = false;
797 m_hasSelfPaintingLayerDescendantDirty = false;
798 m_hasOutOfFlowPositionedDescendantDirty = false;
801 if (m_blendInfo.childLayerHasBlendModeStatusDirty()) {
802 m_blendInfo.setChildLayerHasBlendMode(false);
803 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
804 if (!child->stackingNode()->isStackingContext())
805 child->updateDescendantDependentFlags();
807 bool childLayerHasBlendMode = child->blendInfo().childLayerHasBlendModeWhileDirty();
808 childLayerHasBlendMode |= child->paintsWithBlendMode()
809 || (childLayerHasBlendMode && !child->stackingNode()->isStackingContext());
811 m_blendInfo.setChildLayerHasBlendMode(childLayerHasBlendMode);
813 if (childLayerHasBlendMode)
816 m_blendInfo.setChildLayerHasBlendModeStatusDirty(false);
819 if (m_visibleContentStatusDirty) {
820 if (renderer()->style()->visibility() == VISIBLE)
821 m_hasVisibleContent = true;
823 // layer may be hidden but still have some visible content, check for this
824 m_hasVisibleContent = false;
825 RenderObject* r = renderer()->firstChild();
827 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
828 m_hasVisibleContent = true;
831 if (r->firstChild() && !r->hasLayer())
833 else if (r->nextSibling())
834 r = r->nextSibling();
840 } while (r && !r->nextSibling());
842 r = r->nextSibling();
846 m_visibleContentStatusDirty = false;
850 void RenderLayer::dirty3DTransformedDescendantStatus()
852 RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingContainerNode();
856 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
858 // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
859 // Note that preserves3D() creates stacking context, so we can just run up the stacking containers.
860 while (stackingNode && stackingNode->layer()->preserves3D()) {
861 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
862 stackingNode = stackingNode->ancestorStackingContainerNode();
866 // Return true if this layer or any preserve-3d descendants have 3d.
867 bool RenderLayer::update3DTransformedDescendantStatus()
869 if (m_3DTransformedDescendantStatusDirty) {
870 m_has3DTransformedDescendant = false;
872 m_stackingNode->updateZOrderLists();
874 // Transformed or preserve-3d descendants can only be in the z-order lists, not
875 // in the normal flow list, so we only need to check those.
876 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), PositiveZOrderChildren | NegativeZOrderChildren);
877 while (RenderLayerStackingNode* node = iterator.next())
878 m_has3DTransformedDescendant |= node->layer()->update3DTransformedDescendantStatus();
880 m_3DTransformedDescendantStatusDirty = false;
883 // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
884 // the m_has3DTransformedDescendant set.
886 return has3DTransform() || m_has3DTransformedDescendant;
888 return has3DTransform();
891 bool RenderLayer::updateLayerPosition()
893 LayoutPoint localPoint;
894 LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
895 if (renderer()->isInline() && renderer()->isRenderInline()) {
896 RenderInline* inlineFlow = toRenderInline(renderer());
897 IntRect lineBox = inlineFlow->linesBoundingBox();
898 setSize(lineBox.size());
899 inlineBoundingBoxOffset = toSize(lineBox.location());
900 localPoint += inlineBoundingBoxOffset;
901 } else if (RenderBox* box = renderBox()) {
902 // FIXME: Is snapping the size really needed here for the RenderBox case?
903 setSize(pixelSnappedIntSize(box->size(), box->location()));
904 localPoint += box->topLeftLocationOffset();
907 if (!renderer()->isOutOfFlowPositioned() && renderer()->parent()) {
908 // We must adjust our position by walking up the render tree looking for the
909 // nearest enclosing object with a layer.
910 RenderObject* curr = renderer()->parent();
911 while (curr && !curr->hasLayer()) {
912 if (curr->isBox() && !curr->isTableRow()) {
913 // Rows and cells share the same coordinate space (that of the section).
914 // Omit them when computing our xpos/ypos.
915 localPoint += toRenderBox(curr)->topLeftLocationOffset();
917 curr = curr->parent();
919 if (curr->isBox() && curr->isTableRow()) {
920 // Put ourselves into the row coordinate space.
921 localPoint -= toRenderBox(curr)->topLeftLocationOffset();
925 // Subtract our parent's scroll offset.
926 if (renderer()->isOutOfFlowPositioned() && enclosingPositionedAncestor()) {
927 RenderLayer* positionedParent = enclosingPositionedAncestor();
929 // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
930 if (positionedParent->renderer()->hasOverflowClip()) {
931 LayoutSize offset = positionedParent->renderBox()->scrolledContentOffset();
932 localPoint -= offset;
935 if (renderer()->isOutOfFlowPositioned() && positionedParent->renderer()->isInFlowPositioned() && positionedParent->renderer()->isRenderInline()) {
936 LayoutSize offset = toRenderInline(positionedParent->renderer())->offsetForInFlowPositionedInline(toRenderBox(renderer()));
937 localPoint += offset;
939 } else if (parent()) {
940 if (hasCompositedLayerMapping()) {
941 // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
942 // They won't split across columns properly.
943 LayoutSize columnOffset;
944 if (!parent()->renderer()->hasColumns() && parent()->renderer()->isRoot() && renderer()->view()->hasColumns())
945 renderer()->view()->adjustForColumns(columnOffset, localPoint);
947 parent()->renderer()->adjustForColumns(columnOffset, localPoint);
949 localPoint += columnOffset;
952 if (parent()->renderer()->hasOverflowClip()) {
953 IntSize scrollOffset = parent()->renderBox()->scrolledContentOffset();
954 localPoint -= scrollOffset;
958 bool positionOrOffsetChanged = false;
959 if (renderer()->isInFlowPositioned()) {
960 LayoutSize newOffset = toRenderBoxModelObject(renderer())->offsetForInFlowPosition();
961 positionOrOffsetChanged = newOffset != m_offsetForInFlowPosition;
962 m_offsetForInFlowPosition = newOffset;
963 localPoint.move(m_offsetForInFlowPosition);
965 m_offsetForInFlowPosition = LayoutSize();
968 // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
969 localPoint -= inlineBoundingBoxOffset;
971 positionOrOffsetChanged |= location() != localPoint;
972 setLocation(localPoint);
973 return positionOrOffsetChanged;
976 TransformationMatrix RenderLayer::perspectiveTransform() const
978 if (!renderer()->hasTransform())
979 return TransformationMatrix();
981 RenderStyle* style = renderer()->style();
982 if (!style->hasPerspective())
983 return TransformationMatrix();
985 // Maybe fetch the perspective from the backing?
986 const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
987 const float boxWidth = borderBox.width();
988 const float boxHeight = borderBox.height();
990 float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth);
991 float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight);
993 // A perspective origin of 0,0 makes the vanishing point in the center of the element.
994 // We want it to be in the top-left, so subtract half the height and width.
995 perspectiveOriginX -= boxWidth / 2.0f;
996 perspectiveOriginY -= boxHeight / 2.0f;
998 TransformationMatrix t;
999 t.translate(perspectiveOriginX, perspectiveOriginY);
1000 t.applyPerspective(style->perspective());
1001 t.translate(-perspectiveOriginX, -perspectiveOriginY);
1006 FloatPoint RenderLayer::perspectiveOrigin() const
1008 if (!renderer()->hasTransform())
1009 return FloatPoint();
1011 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
1012 RenderStyle* style = renderer()->style();
1014 return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width()),
1015 floatValueForLength(style->perspectiveOriginY(), borderBox.height()));
1018 static inline bool isFixedPositionedContainer(RenderLayer* layer)
1020 return layer->isRootLayer() || layer->hasTransform();
1023 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
1025 RenderLayer* curr = parent();
1026 while (curr && !curr->isPositionedContainer())
1027 curr = curr->parent();
1032 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
1034 RenderLayer* curr = parent();
1035 while (curr && !curr->isRootLayer() && !curr->transform())
1036 curr = curr->parent();
1041 const RenderLayer* RenderLayer::compositingContainer() const
1043 return stackingNode()->isNormalFlowOnly() ? parent() : (stackingNode()->ancestorStackingContainerNode() ? stackingNode()->ancestorStackingContainerNode()->layer() : 0);
1046 // FIXME: having two different functions named enclosingCompositingLayer and enclosingCompositingLayerForRepaint
1047 // is error-prone and misleading for reading code that uses these functions - especially compounded with
1048 // the includeSelf option. It is very likely that we don't even want either of these functions; A layer
1049 // should be told explicitly which GraphicsLayer is the repaintContainer for a RenderLayer, and
1050 // any other use cases should probably have an API between the non-compositing and compositing sides of code.
1051 RenderLayer* RenderLayer::enclosingCompositingLayer(IncludeSelfOrNot includeSelf) const
1053 if ((includeSelf == IncludeSelf) && compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking)
1054 return const_cast<RenderLayer*>(this);
1056 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
1057 if (curr->compositingState() != NotComposited && curr->compositingState() != PaintsIntoGroupedBacking)
1058 return const_cast<RenderLayer*>(curr);
1064 RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(IncludeSelfOrNot includeSelf) const
1066 if ((includeSelf == IncludeSelf) && (compositingState() == PaintsIntoOwnBacking || compositingState() == PaintsIntoGroupedBacking))
1067 return const_cast<RenderLayer*>(this);
1069 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->compositingContainer()) {
1070 if (curr->compositingState() == PaintsIntoOwnBacking || curr->compositingState() == PaintsIntoGroupedBacking)
1071 return const_cast<RenderLayer*>(curr);
1077 RenderLayer* RenderLayer::ancestorCompositedScrollingLayer() const
1079 if (!renderer()->acceleratedCompositingForOverflowScrollEnabled())
1082 RenderObject* containingBlock = renderer()->containingBlock();
1083 if (!containingBlock)
1086 for (RenderLayer* ancestorLayer = containingBlock->enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) {
1087 if (ancestorLayer->needsCompositedScrolling())
1088 return ancestorLayer;
1094 RenderLayer* RenderLayer::ancestorScrollingLayer() const
1096 RenderObject* containingBlock = renderer()->containingBlock();
1097 if (!containingBlock)
1100 for (RenderLayer* ancestorLayer = containingBlock->enclosingLayer(); ancestorLayer; ancestorLayer = ancestorLayer->parent()) {
1101 if (ancestorLayer->scrollsOverflow())
1102 return ancestorLayer;
1108 RenderLayer* RenderLayer::enclosingFilterLayer(IncludeSelfOrNot includeSelf) const
1110 const RenderLayer* curr = (includeSelf == IncludeSelf) ? this : parent();
1111 for (; curr; curr = curr->parent()) {
1112 if (curr->requiresFullLayerImageForFilters())
1113 return const_cast<RenderLayer*>(curr);
1119 bool RenderLayer::hasAncestorWithFilterOutsets() const
1121 for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
1122 RenderLayerModelObject* renderer = curr->renderer();
1123 if (renderer->style()->hasFilterOutsets())
1129 bool RenderLayer::cannotBlitToWindow() const
1131 if (isTransparent() || m_reflectionInfo || hasTransform())
1135 return parent()->cannotBlitToWindow();
1138 bool RenderLayer::isTransparent() const
1140 if (renderer()->node() && renderer()->node()->isSVGElement())
1143 return renderer()->isTransparent() || renderer()->hasMask();
1146 RenderLayer* RenderLayer::transparentPaintingAncestor()
1148 if (hasCompositedLayerMapping())
1151 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
1152 if (curr->hasCompositedLayerMapping())
1154 if (curr->isTransparent())
1160 enum TransparencyClipBoxBehavior {
1161 PaintingTransparencyClipBox,
1162 HitTestingTransparencyClipBox
1165 enum TransparencyClipBoxMode {
1166 DescendantsOfTransparencyClipBox,
1167 RootOfTransparencyClipBox
1170 static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, PaintBehavior = 0);
1172 static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer,
1173 TransparencyClipBoxBehavior transparencyBehavior, PaintBehavior paintBehavior)
1175 // If we have a mask, then the clip is limited to the border box area (and there is
1176 // no need to examine child layers).
1177 if (!layer->renderer()->hasMask()) {
1178 // Note: we don't have to walk z-order lists since transparent elements always establish
1179 // a stacking container. This means we can just walk the layer tree directly.
1180 for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) {
1181 if (!layer->reflectionInfo() || layer->reflectionInfo()->reflectionLayer() != curr)
1182 clipRect.unite(transparencyClipBox(curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, paintBehavior));
1186 // If we have a reflection, then we need to account for that when we push the clip. Reflect our entire
1187 // current transparencyClipBox to catch all child layers.
1188 // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
1189 // size into the parent layer.
1190 if (layer->renderer()->hasReflection()) {
1192 layer->convertToLayerCoords(rootLayer, delta);
1193 clipRect.move(-delta.x(), -delta.y());
1194 clipRect.unite(layer->renderBox()->reflectedRect(clipRect));
1195 clipRect.moveBy(delta);
1199 static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
1200 TransparencyClipBoxMode transparencyMode, PaintBehavior paintBehavior)
1202 // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
1203 // paintDirtyRect, and that should cut down on the amount we have to paint. Still it
1204 // would be better to respect clips.
1206 if (rootLayer != layer && ((transparencyBehavior == PaintingTransparencyClipBox && layer->paintsWithTransform(paintBehavior))
1207 || (transparencyBehavior == HitTestingTransparencyClipBox && layer->hasTransform()))) {
1208 // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
1209 // the transformed layer and all of its children.
1210 const RenderLayer* paginationLayer = transparencyMode == DescendantsOfTransparencyClipBox ? layer->enclosingPaginationLayer() : 0;
1211 const RenderLayer* rootLayerForTransform = paginationLayer ? paginationLayer : rootLayer;
1213 layer->convertToLayerCoords(rootLayerForTransform, delta);
1215 TransformationMatrix transform;
1216 transform.translate(delta.x(), delta.y());
1217 transform = transform * *layer->transform();
1219 // We don't use fragment boxes when collecting a transformed layer's bounding box, since it always
1220 // paints unfragmented.
1221 LayoutRect clipRect = layer->boundingBox(layer);
1222 expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, paintBehavior);
1223 layer->renderer()->style()->filterOutsets().expandRect(clipRect);
1224 LayoutRect result = transform.mapRect(clipRect);
1225 if (!paginationLayer)
1228 // We have to break up the transformed extent across our columns.
1229 // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
1230 // get our true bounding box.
1231 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(paginationLayer->renderer());
1232 result = enclosingFlowThread->fragmentsBoundingBox(result);
1234 LayoutPoint rootLayerDelta;
1235 paginationLayer->convertToLayerCoords(rootLayer, rootLayerDelta);
1236 result.moveBy(rootLayerDelta);
1240 LayoutRect clipRect = layer->boundingBox(rootLayer, RenderLayer::UseFragmentBoxes);
1241 expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, paintBehavior);
1242 layer->renderer()->style()->filterOutsets().expandRect(clipRect);
1246 LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
1248 return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintBehavior), paintDirtyRect);
1251 void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
1253 bool createTransparencyLayerForBlendMode = m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode();
1254 if (context->paintingDisabled() || ((paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency))
1257 RenderLayer* ancestor = transparentPaintingAncestor();
1259 ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
1261 if (paintsWithTransparency(paintBehavior) || paintsWithBlendMode() || createTransparencyLayerForBlendMode) {
1262 m_usedTransparency = true;
1264 LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, paintBehavior);
1265 context->clip(clipRect);
1267 if (paintsWithBlendMode())
1268 context->setCompositeOperation(context->compositeOperation(), m_blendInfo.blendMode());
1270 context->beginTransparencyLayer(renderer()->opacity());
1272 if (paintsWithBlendMode())
1273 context->setCompositeOperation(context->compositeOperation(), blink::WebBlendModeNormal);
1274 #ifdef REVEAL_TRANSPARENCY_LAYERS
1275 context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f));
1276 context->fillRect(clipRect);
1281 void* RenderLayer::operator new(size_t sz)
1283 return partitionAlloc(Partitions::getRenderingPartition(), sz);
1286 void RenderLayer::operator delete(void* ptr)
1291 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
1293 RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
1295 child->setPreviousSibling(prevSibling);
1296 prevSibling->setNextSibling(child);
1297 ASSERT(prevSibling != child);
1299 setFirstChild(child);
1302 beforeChild->setPreviousSibling(child);
1303 child->setNextSibling(beforeChild);
1304 ASSERT(beforeChild != child);
1306 setLastChild(child);
1308 child->setParent(this);
1310 if (child->stackingNode()->isNormalFlowOnly())
1311 m_stackingNode->dirtyNormalFlowList();
1313 if (!child->stackingNode()->isNormalFlowOnly() || child->firstChild()) {
1314 // Dirty the z-order list in which we are contained. The ancestorStackingContainerNode() can be null in the
1315 // case where we're building up generated content layers. This is ok, since the lists will start
1316 // off dirty in that case anyway.
1317 child->stackingNode()->dirtyStackingContainerZOrderLists();
1320 child->updateDescendantDependentFlags();
1321 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
1322 setAncestorChainHasVisibleDescendant();
1324 if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
1325 setAncestorChainHasSelfPaintingLayerDescendant();
1327 if (child->paintsWithBlendMode() || child->blendInfo().childLayerHasBlendMode())
1328 m_blendInfo.setAncestorChainBlendedDescendant();
1330 if (subtreeContainsOutOfFlowPositionedLayer(child)) {
1331 // Now that the out of flow positioned descendant is in the tree, we
1332 // need to tell the compositor to reevaluate the compositing
1333 // requirements since we may be able to mark more layers as having
1334 // an 'unclipped' descendant.
1335 compositor()->setNeedsUpdateCompositingRequirementsState();
1336 setAncestorChainHasOutOfFlowPositionedDescendant();
1339 // When we first dirty a layer, we will also dirty all the siblings in that
1340 // layer's stacking context. We need to manually do it here as well, in case
1341 // we're adding this layer after the stacking context has already been
1343 child->stackingNode()->setDescendantsAreContiguousInStackingOrderDirty(true);
1344 compositor()->layerWasAdded(this, child);
1347 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
1349 if (!renderer()->documentBeingDestroyed())
1350 compositor()->layerWillBeRemoved(this, oldChild);
1353 if (oldChild->previousSibling())
1354 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
1355 if (oldChild->nextSibling())
1356 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
1358 if (m_first == oldChild)
1359 m_first = oldChild->nextSibling();
1360 if (m_last == oldChild)
1361 m_last = oldChild->previousSibling();
1363 if (oldChild->stackingNode()->isNormalFlowOnly())
1364 m_stackingNode->dirtyNormalFlowList();
1365 if (!oldChild->stackingNode()->isNormalFlowOnly() || oldChild->firstChild()) {
1366 // Dirty the z-order list in which we are contained. When called via the
1367 // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
1368 // from the main layer tree, so we need to null-check the |stackingContainer| value.
1369 oldChild->stackingNode()->dirtyStackingContainerZOrderLists();
1372 oldChild->setPreviousSibling(0);
1373 oldChild->setNextSibling(0);
1374 oldChild->setParent(0);
1376 oldChild->updateDescendantDependentFlags();
1377 if (subtreeContainsOutOfFlowPositionedLayer(oldChild)) {
1378 // It may now be the case that a layer no longer has an unclipped
1379 // descendant. Let the compositor know that it needs to reevaluate
1380 // its compositing requirements to check this.
1381 compositor()->setNeedsUpdateCompositingRequirementsState();
1382 dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
1385 if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
1386 dirtyAncestorChainVisibleDescendantStatus();
1388 if (oldChild->paintsWithBlendMode() || oldChild->blendInfo().childLayerHasBlendMode())
1389 m_blendInfo.dirtyAncestorChainBlendedDescendantStatus();
1391 if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
1392 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
1397 void RenderLayer::removeOnlyThisLayer()
1402 compositor()->layerWillBeRemoved(m_parent, this);
1404 // Dirty the clip rects.
1405 m_clipper.clearClipRectsIncludingDescendants();
1407 RenderLayer* nextSib = nextSibling();
1409 // Remove the child reflection layer before moving other child layers.
1410 // The reflection layer should not be moved to the parent.
1411 if (m_reflectionInfo)
1412 removeChild(m_reflectionInfo->reflectionLayer());
1414 // Now walk our kids and reattach them to our parent.
1415 RenderLayer* current = m_first;
1417 RenderLayer* next = current->nextSibling();
1418 removeChild(current);
1419 m_parent->addChild(current, nextSib);
1420 current->repainter().setRepaintStatus(NeedsFullRepaint);
1421 current->updateLayerPositions(0); // FIXME: use geometry map.
1425 // Remove us from the parent.
1426 m_parent->removeChild(this);
1427 m_renderer->destroyLayer();
1430 void RenderLayer::insertOnlyThisLayer()
1432 if (!m_parent && renderer()->parent()) {
1433 // We need to connect ourselves when our renderer() has a parent.
1434 // Find our enclosingLayer and add ourselves.
1435 RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
1436 ASSERT(parentLayer);
1437 RenderLayer* beforeChild = !parentLayer->reflectionInfo() || parentLayer->reflectionInfo()->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
1438 parentLayer->addChild(this, beforeChild);
1441 // Remove all descendant layers from the hierarchy and add them to the new position.
1442 for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
1443 curr->moveLayers(m_parent, this);
1445 // Clear out all the clip rects.
1446 m_clipper.clearClipRectsIncludingDescendants();
1449 void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& roundedLocation) const
1451 LayoutPoint location = roundedLocation;
1452 convertToLayerCoords(ancestorLayer, location);
1453 roundedLocation = roundedIntPoint(location);
1456 void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect& roundedRect) const
1458 LayoutRect rect = roundedRect;
1459 convertToLayerCoords(ancestorLayer, rect);
1460 roundedRect = pixelSnappedIntRect(rect);
1463 // Returns the layer reached on the walk up towards the ancestor.
1464 static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer, LayoutPoint& location)
1466 ASSERT(ancestorLayer != layer);
1468 const RenderLayerModelObject* renderer = layer->renderer();
1469 EPosition position = renderer->style()->position();
1471 // FIXME: Special casing RenderFlowThread so much for fixed positioning here is not great.
1472 RenderFlowThread* fixedFlowThreadContainer = position == FixedPosition ? renderer->flowThreadContainingBlock() : 0;
1473 if (fixedFlowThreadContainer && !fixedFlowThreadContainer->isOutOfFlowPositioned())
1474 fixedFlowThreadContainer = 0;
1476 // FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread
1477 // may need to be revisited in a future patch.
1478 // If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute,
1479 // since localToAbsolute maps the coordinates from named flow to regions coordinates and regions can be
1480 // positioned in a completely different place in the viewport (RenderView).
1481 if (position == FixedPosition && !fixedFlowThreadContainer && (!ancestorLayer || ancestorLayer == renderer->view()->layer())) {
1482 // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
1483 // localToAbsolute() on the RenderView.
1484 FloatPoint absPos = renderer->localToAbsolute(FloatPoint(), IsFixed);
1485 location += LayoutSize(absPos.x(), absPos.y());
1486 return ancestorLayer;
1489 // For the fixed positioned elements inside a render flow thread, we should also skip the code path below
1490 // Otherwise, for the case of ancestorLayer == rootLayer and fixed positioned element child of a transformed
1491 // element in render flow thread, we will hit the fixed positioned container before hitting the ancestor layer.
1492 if (position == FixedPosition && !fixedFlowThreadContainer) {
1493 // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
1494 // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
1495 // so we should always find the ancestor at or before we find the fixed position container.
1496 RenderLayer* fixedPositionContainerLayer = 0;
1497 bool foundAncestor = false;
1498 for (RenderLayer* currLayer = layer->parent(); currLayer; currLayer = currLayer->parent()) {
1499 if (currLayer == ancestorLayer)
1500 foundAncestor = true;
1502 if (isFixedPositionedContainer(currLayer)) {
1503 fixedPositionContainerLayer = currLayer;
1504 ASSERT_UNUSED(foundAncestor, foundAncestor);
1509 ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
1511 if (fixedPositionContainerLayer != ancestorLayer) {
1512 LayoutPoint fixedContainerCoords;
1513 layer->convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
1515 LayoutPoint ancestorCoords;
1516 ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords);
1518 location += (fixedContainerCoords - ancestorCoords);
1520 location += toSize(layer->location());
1522 return ancestorLayer;
1525 RenderLayer* parentLayer;
1526 if (position == AbsolutePosition || position == FixedPosition) {
1527 // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
1528 parentLayer = layer->parent();
1529 bool foundAncestorFirst = false;
1530 while (parentLayer) {
1531 // RenderFlowThread is a positioned container, child of RenderView, positioned at (0,0).
1532 // This implies that, for out-of-flow positioned elements inside a RenderFlowThread,
1533 // we are bailing out before reaching root layer.
1534 if (parentLayer->isPositionedContainer())
1537 if (parentLayer == ancestorLayer) {
1538 foundAncestorFirst = true;
1542 parentLayer = parentLayer->parent();
1545 // We should not reach RenderView layer past the RenderFlowThread layer for any
1546 // children of the RenderFlowThread.
1547 if (renderer->flowThreadContainingBlock() && !layer->isOutOfFlowRenderFlowThread())
1548 ASSERT(parentLayer != renderer->view()->layer());
1550 if (foundAncestorFirst) {
1551 // Found ancestorLayer before the abs. positioned container, so compute offset of both relative
1552 // to enclosingPositionedAncestor and subtract.
1553 RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
1555 LayoutPoint thisCoords;
1556 layer->convertToLayerCoords(positionedAncestor, thisCoords);
1558 LayoutPoint ancestorCoords;
1559 ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords);
1561 location += (thisCoords - ancestorCoords);
1562 return ancestorLayer;
1565 parentLayer = layer->parent();
1570 location += toSize(layer->location());
1574 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const
1576 if (ancestorLayer == this)
1579 const RenderLayer* currLayer = this;
1580 while (currLayer && currLayer != ancestorLayer)
1581 currLayer = accumulateOffsetTowardsAncestor(currLayer, ancestorLayer, location);
1584 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const
1587 convertToLayerCoords(ancestorLayer, delta);
1588 rect.move(-delta.x(), -delta.y());
1591 RenderLayer* RenderLayer::scrollParent() const
1593 if (!renderer()->compositorDrivenAcceleratedScrollingEnabled())
1596 // Normal flow elements will be parented under the main scrolling layer, so
1597 // we don't need a scroll parent/child relationship to get them to scroll.
1598 if (stackingNode()->isNormalFlowOnly())
1601 // A layer scrolls with its containing block. So to find the overflow scrolling layer
1602 // that we scroll with respect to, we must ascend the layer tree until we reach the
1603 // first overflow scrolling div at or above our containing block. I will refer to this
1604 // layer as our 'scrolling ancestor'.
1606 // Now, if we reside in a normal flow list, then we will naturally scroll with our scrolling
1607 // ancestor, and we need not be composited. If, on the other hand, we reside in a z-order
1608 // list, and on our walk upwards to our scrolling ancestor we find no layer that is a stacking
1609 // context, then we know that in the stacking tree, we will not be in the subtree rooted at
1610 // our scrolling ancestor, and we will therefore not scroll with it. In this case, we must
1611 // be a composited layer since the compositor will need to take special measures to ensure
1612 // that we scroll with our scrolling ancestor and it cannot do this if we do not promote.
1613 RenderLayer* scrollParent = ancestorCompositedScrollingLayer();
1615 if (!scrollParent || scrollParent->stackingNode()->isStackingContainer())
1618 // If we hit a stacking context on our way up to the ancestor scrolling layer, it will already
1619 // be composited due to an overflow scrolling parent, so we don't need to.
1620 for (RenderLayer* ancestor = parent(); ancestor && ancestor != scrollParent; ancestor = ancestor->parent()) {
1621 if (ancestor->stackingNode()->isStackingContainer())
1625 return scrollParent;
1628 RenderLayer* RenderLayer::clipParent() const
1630 const bool needsAncestorClip = compositor()->clippedByAncestor(this);
1632 RenderLayer* clipParent = 0;
1633 if ((compositingReasons() & CompositingReasonOutOfFlowClipping) && !needsAncestorClip) {
1634 if (RenderObject* containingBlock = renderer()->containingBlock())
1635 clipParent = containingBlock->enclosingLayer()->enclosingCompositingLayer();
1641 void RenderLayer::didUpdateNeedsCompositedScrolling()
1643 m_stackingNode->updateIsNormalFlowOnly();
1644 updateSelfPaintingLayer();
1646 if (m_stackingNode->isStackingContainer())
1647 m_stackingNode->dirtyZOrderLists();
1649 m_stackingNode->clearZOrderLists();
1651 m_stackingNode->dirtyStackingContainerZOrderLists();
1653 compositor()->setNeedsToRecomputeCompositingRequirements();
1654 compositor()->setCompositingLayersNeedRebuild();
1657 void RenderLayer::updateReflectionInfo(const RenderStyle* oldStyle)
1659 if (renderer()->hasReflection()) {
1660 if (!m_reflectionInfo)
1661 m_reflectionInfo = adoptPtr(new RenderLayerReflectionInfo(toRenderBox(renderer())));
1662 m_reflectionInfo->updateAfterStyleChange(oldStyle);
1663 } else if (m_reflectionInfo) {
1664 m_reflectionInfo = nullptr;
1668 void RenderLayer::updateStackingNode()
1670 if (requiresStackingNode())
1671 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this));
1673 m_stackingNode = nullptr;
1676 void RenderLayer::updateScrollableArea()
1678 if (requiresScrollableArea())
1679 m_scrollableArea = adoptPtr(new RenderLayerScrollableArea(renderBox()));
1681 m_scrollableArea = nullptr;
1684 PassOwnPtr<Vector<FloatRect> > RenderLayer::collectTrackedRepaintRects() const
1686 if (hasCompositedLayerMapping())
1687 return compositedLayerMapping()->collectTrackedRepaintRects();
1691 bool RenderLayer::hasOverflowControls() const
1693 return m_scrollableArea && (m_scrollableArea->hasScrollbar() || m_scrollableArea->hasScrollCorner() || renderer()->style()->resize() != RESIZE_NONE);
1696 void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderRegion* region, PaintLayerFlags paintFlags)
1698 OverlapTestRequestMap overlapTestRequests;
1700 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, region, &overlapTestRequests);
1701 paintLayer(context, paintingInfo, paintFlags);
1703 OverlapTestRequestMap::iterator end = overlapTestRequests.end();
1704 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
1705 it->key->setIsOverlapped(false);
1708 void RenderLayer::paintOverlayScrollbars(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot)
1710 if (!m_containsDirtyOverlayScrollbars)
1713 LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot);
1714 paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
1716 m_containsDirtyOverlayScrollbars = false;
1719 static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer)
1721 if (startLayer == endLayer)
1724 RenderView* view = startLayer->renderer()->view();
1725 for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlock()) {
1726 if (currentBlock->layer() == endLayer)
1733 void RenderLayer::clipToRect(RenderLayer* rootLayer, GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect,
1734 BorderRadiusClippingRule rule)
1736 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
1739 context->clip(pixelSnappedIntRect(clipRect.rect()));
1741 if (!clipRect.hasRadius())
1744 // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
1745 // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
1746 // containing block chain so we check that also.
1747 for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) {
1748 if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(this, layer)) {
1750 layer->convertToLayerCoords(rootLayer, delta);
1751 context->clipRoundedRect(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size())));
1754 if (layer == rootLayer)
1759 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect)
1761 if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
1766 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
1768 Vector<RenderWidget*> overlappedRequestClients;
1769 OverlapTestRequestMap::iterator end = overlapTestRequests.end();
1770 LayoutRect boundingBox = layer->boundingBox(rootLayer);
1771 for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
1772 if (!boundingBox.intersects(it->value))
1775 it->key->setIsOverlapped(true);
1776 overlappedRequestClients.append(it->key);
1778 for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
1779 overlapTestRequests.remove(overlappedRequestClients[i]);
1782 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
1784 return paintingReflection && !layer->has3DTransform();
1787 static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
1789 // Avoid painting descendants of the root layer when stylesheets haven't loaded. This eliminates FOUC.
1790 // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
1791 // will do a full repaint().
1792 if (layer->renderer()->document().didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isRoot())
1798 static bool paintForFixedRootBackground(const RenderLayer* layer, PaintLayerFlags paintFlags)
1800 return layer->renderer()->isRoot() && (paintFlags & PaintLayerPaintingRootBackgroundOnly);
1803 void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
1805 if (compositingState() != NotComposited && compositingState() != PaintsIntoGroupedBacking) {
1806 // The updatingControlTints() painting pass goes through compositing layers,
1807 // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
1808 if (context->updatingControlTints() || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers)) {
1809 paintFlags |= PaintLayerTemporaryClipRects;
1810 } else if (!compositedLayerMapping()->paintsIntoCompositedAncestor()
1811 && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)
1812 && !paintForFixedRootBackground(this, paintFlags)) {
1813 // If this RenderLayer should paint into its own backing, that will be done via CompositedLayerMapping::paintIntoLayer().
1816 } else if (viewportConstrainedNotCompositedReason() == NotCompositedForBoundsOutOfView) {
1817 // Don't paint out-of-view viewport constrained layers (when doing prepainting) because they will never be visible
1818 // unless their position or viewport size is changed.
1822 // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself.
1823 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
1826 if (shouldSuppressPaintingLayer(this))
1829 // If this layer is totally invisible then there is nothing to paint.
1830 if (!renderer()->opacity())
1833 if (paintsWithTransparency(paintingInfo.paintBehavior))
1834 paintFlags |= PaintLayerHaveTransparency;
1836 // PaintLayerAppliedTransform is used in RenderReplica, to avoid applying the transform twice.
1837 if (paintsWithTransform(paintingInfo.paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
1838 TransformationMatrix layerTransform = renderableTransform(paintingInfo.paintBehavior);
1839 // If the transform can't be inverted, then don't paint anything.
1840 if (!layerTransform.isInvertible())
1843 // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
1844 // layer from the parent now, assuming there is a parent
1845 if (paintFlags & PaintLayerHaveTransparency) {
1847 parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
1849 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
1852 if (enclosingPaginationLayer()) {
1853 paintTransformedLayerIntoFragments(context, paintingInfo, paintFlags);
1857 // Make sure the parent's clip rects have been calculated.
1858 ClipRect clipRect = paintingInfo.paintDirtyRect;
1860 ClipRectsContext clipRectsContext(paintingInfo.rootLayer, paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
1861 IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
1862 clipRect = clipper().backgroundClipRect(clipRectsContext);
1863 clipRect.intersect(paintingInfo.paintDirtyRect);
1865 // Push the parent coordinate space's clip.
1866 parent()->clipToRect(paintingInfo.rootLayer, context, paintingInfo.paintDirtyRect, clipRect);
1869 paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
1871 // Restore the clip.
1873 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
1878 paintLayerContentsAndReflection(context, paintingInfo, paintFlags);
1881 void RenderLayer::paintLayerContentsAndReflection(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
1883 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
1885 PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform);
1887 // Paint the reflection first if we have one.
1888 if (m_reflectionInfo)
1889 m_reflectionInfo->paint(context, paintingInfo, localPaintFlags | PaintLayerPaintingReflection);
1891 localPaintFlags |= PaintLayerPaintingCompositingAllPhases;
1892 paintLayerContents(context, paintingInfo, localPaintFlags);
1895 void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
1897 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
1898 ASSERT(!(paintFlags & PaintLayerAppliedTransform));
1900 bool haveTransparency = paintFlags & PaintLayerHaveTransparency;
1901 bool isSelfPaintingLayer = this->isSelfPaintingLayer();
1902 bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars;
1903 bool isPaintingScrollingContent = paintFlags & PaintLayerPaintingCompositingScrollingPhase;
1904 bool isPaintingCompositedForeground = paintFlags & PaintLayerPaintingCompositingForegroundPhase;
1905 bool isPaintingCompositedBackground = paintFlags & PaintLayerPaintingCompositingBackgroundPhase;
1906 bool isPaintingOverflowContents = paintFlags & PaintLayerPaintingOverflowContents;
1907 // Outline always needs to be painted even if we have no visible content. Also,
1908 // the outline is painted in the background phase during composited scrolling.
1909 // If it were painted in the foreground phase, it would move with the scrolled
1910 // content. When not composited scrolling, the outline is painted in the
1911 // foreground phase. Since scrolled contents are moved by repainting in this
1912 // case, the outline won't get 'dragged along'.
1913 bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars
1914 && ((isPaintingScrollingContent && isPaintingCompositedBackground)
1915 || (!isPaintingScrollingContent && isPaintingCompositedForeground));
1916 bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars;
1918 float deviceScaleFactor = WebCore::deviceScaleFactor(renderer()->frame());
1919 context->setUseHighResMarkers(deviceScaleFactor > 1.5f);
1921 GraphicsContext* transparencyLayerContext = context;
1923 if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer()->isRenderView() && !renderer()->isRoot())
1926 // Ensure our lists are up-to-date.
1927 m_stackingNode->updateLayerListsIfNeeded();
1929 LayoutPoint offsetFromRoot;
1930 convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
1932 if (compositingState() == PaintsIntoOwnBacking)
1933 offsetFromRoot.move(m_compositedLayerMapping->subpixelAccumulation());
1935 LayoutRect rootRelativeBounds;
1936 bool rootRelativeBoundsComputed = false;
1938 // Apply clip-path to context.
1939 bool hasClipPath = false;
1940 RenderStyle* style = renderer()->style();
1941 RenderSVGResourceClipper* resourceClipper = 0;
1942 ClipperContext clipperContext;
1943 if (renderer()->hasClipPath() && !context->paintingDisabled() && style) {
1944 ASSERT(style->clipPath());
1945 if (style->clipPath()->type() == ClipPathOperation::SHAPE) {
1948 ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style->clipPath());
1950 if (!rootRelativeBoundsComputed) {
1951 rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
1952 rootRelativeBoundsComputed = true;
1955 context->clipPath(clipPath->path(rootRelativeBounds), clipPath->windRule());
1956 } else if (style->clipPath()->type() == ClipPathOperation::REFERENCE) {
1957 ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClipPathOperation(style->clipPath());
1958 Document& document = renderer()->document();
1959 // FIXME: It doesn't work with forward or external SVG references (https://bugs.webkit.org/show_bug.cgi?id=90405)
1960 Element* element = document.getElementById(referenceClipPathOperation->fragment());
1961 if (element && element->hasTagName(SVGNames::clipPathTag) && element->renderer()) {
1962 if (!rootRelativeBoundsComputed) {
1963 rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
1964 rootRelativeBoundsComputed = true;
1967 resourceClipper = toRenderSVGResourceClipper(toRenderSVGResourceContainer(element->renderer()));
1968 if (!resourceClipper->applyClippingToContext(renderer(), rootRelativeBounds,
1969 paintingInfo.paintDirtyRect, context, clipperContext)) {
1970 // No need to post-apply the clipper if this failed.
1971 resourceClipper = 0;
1977 // Blending operations must be performed only with the nearest ancestor stacking context.
1978 // Note that there is no need to create a transparency layer if we're painting the root.
1979 bool createTransparencyLayerForBlendMode = !renderer()->isRoot() && m_stackingNode->isStackingContext() && m_blendInfo.childLayerHasBlendMode();
1981 if (createTransparencyLayerForBlendMode)
1982 beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
1984 LayerPaintingInfo localPaintingInfo(paintingInfo);
1985 FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
1986 if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
1987 RenderLayerFilterInfo* filterInfo = this->filterInfo();
1989 LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
1990 filterRepaintRect.move(offsetFromRoot.x(), offsetFromRoot.y());
1992 if (!rootRelativeBoundsComputed)
1993 rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
1995 if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, paintingInfo.paintDirtyRect, filterRepaintRect)) {
1996 // Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
1997 filterInfo->resetDirtySourceRect();
1999 // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
2000 // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
2001 // on the original context and avoid duplicating "beginFilterEffect" after each transparency layer call. Also, note that
2002 // beginTransparencyLayers will only create a single lazy transparency layer, even though it is called twice in this method.
2003 context = filterPainter.beginFilterEffect(context);
2005 // Check that we didn't fail to allocate the graphics context for the offscreen buffer.
2006 if (filterPainter.hasStartedFilterEffect()) {
2007 localPaintingInfo.paintDirtyRect = filterPainter.repaintRect();
2008 // If the filter needs the full source image, we need to avoid using the clip rectangles.
2009 // Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly.
2010 // Note that we will still apply the clipping on the final rendering of the filter.
2011 localPaintingInfo.clipToDirtyRect = !filterRenderer()->hasFilterThatMovesPixels();
2016 if (filterPainter.hasStartedFilterEffect() && haveTransparency) {
2017 // 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.
2018 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, localPaintingInfo.paintBehavior);
2021 // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
2022 // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
2023 // Else, our renderer tree may or may not contain the painting root, so we pass that root along
2024 // so it will be tested against as we descend through the renderers.
2025 RenderObject* paintingRootForRenderer = 0;
2026 if (localPaintingInfo.paintingRoot && !renderer()->isDescendantOf(localPaintingInfo.paintingRoot))
2027 paintingRootForRenderer = localPaintingInfo.paintingRoot;
2029 if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer)
2030 performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this);
2032 bool forceBlackText = localPaintingInfo.paintBehavior & PaintBehaviorForceBlackText;
2033 bool selectionOnly = localPaintingInfo.paintBehavior & PaintBehaviorSelectionOnly;
2035 bool shouldPaintBackground = isPaintingCompositedBackground && shouldPaintContent && !selectionOnly;
2036 bool shouldPaintNegZOrderList = (isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground);
2037 bool shouldPaintOwnContents = isPaintingCompositedForeground && shouldPaintContent;
2038 bool shouldPaintNormalFlowAndPosZOrderLists = isPaintingCompositedForeground;
2039 bool shouldPaintOverlayScrollbars = isPaintingOverlayScrollbars;
2040 bool shouldPaintMask = (paintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly;
2041 bool shouldPaintClippingMask = (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && shouldPaintContent && !selectionOnly;
2043 PaintBehavior paintBehavior = PaintBehaviorNormal;
2044 if (paintFlags & PaintLayerPaintingSkipRootBackground)
2045 paintBehavior |= PaintBehaviorSkipRootBackground;
2046 else if (paintFlags & PaintLayerPaintingRootBackgroundOnly)
2047 paintBehavior |= PaintBehaviorRootBackgroundOnly;
2049 LayerFragments layerFragments;
2050 if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
2051 // 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
2052 // fragment should paint.
2053 collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.region, localPaintingInfo.paintDirtyRect,
2054 (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
2055 (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetFromRoot, localPaintingInfo.subPixelAccumulation);
2056 updatePaintingInfoForFragments(layerFragments, localPaintingInfo, paintFlags, shouldPaintContent, &offsetFromRoot);
2059 if (shouldPaintBackground)
2060 paintBackgroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
2061 localPaintingInfo, paintBehavior, paintingRootForRenderer);
2063 if (shouldPaintNegZOrderList)
2064 paintChildren(NegativeZOrderChildren, context, localPaintingInfo, paintFlags);
2066 if (shouldPaintOwnContents)
2067 paintForegroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
2068 localPaintingInfo, paintBehavior, paintingRootForRenderer, selectionOnly, forceBlackText);
2070 if (shouldPaintOutline)
2071 paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintBehavior, paintingRootForRenderer);
2073 if (shouldPaintNormalFlowAndPosZOrderLists)
2074 paintChildren(NormalFlowChildren | PositiveZOrderChildren, context, localPaintingInfo, paintFlags);
2076 if (shouldPaintOverlayScrollbars)
2077 paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo);
2079 if (filterPainter.hasStartedFilterEffect()) {
2080 // Apply the correct clipping (ie. overflow: hidden).
2081 // FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
2082 ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
2083 clipToRect(localPaintingInfo.rootLayer, transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
2084 context = filterPainter.applyFilterEffect();
2085 restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
2088 // Make sure that we now use the original transparency context.
2089 ASSERT(transparencyLayerContext == context);
2091 if (shouldPaintMask)
2092 paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer);
2094 if (shouldPaintClippingMask) {
2095 // Paint the border radius mask for the fragments.
2096 paintChildClippingMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer);
2099 // End our transparency layer
2100 if ((haveTransparency || paintsWithBlendMode() || createTransparencyLayerForBlendMode) && m_usedTransparency && !(m_reflectionInfo && m_reflectionInfo->isPaintingInsideReflection())) {
2101 context->endLayer();
2103 m_usedTransparency = false;
2106 if (resourceClipper)
2107 resourceClipper->postApplyStatefulResource(renderer(), context, clipperContext);
2113 void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, const LayoutPoint& translationOffset)
2115 // This involves subtracting out the position of the layer in our current coordinate space, but preserving
2116 // the accumulated error for sub-pixel layout.
2118 convertToLayerCoords(paintingInfo.rootLayer, delta);
2119 delta.moveBy(translationOffset);
2120 TransformationMatrix transform(renderableTransform(paintingInfo.paintBehavior));
2121 IntPoint roundedDelta = roundedIntPoint(delta);
2122 transform.translateRight(roundedDelta.x(), roundedDelta.y());
2123 LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
2125 // Apply the transform.
2126 GraphicsContextStateSaver stateSaver(*context);
2127 context->concatCTM(transform.toAffineTransform());
2129 // Now do a paint with the root layer shifted to be us.
2130 LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)), paintingInfo.paintBehavior,
2131 adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.region, paintingInfo.overlapTestRequests);
2132 paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags);
2135 void RenderLayer::paintChildren(unsigned childrenToVisit, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2137 if (!hasSelfPaintingLayerDescendant())
2140 #if !ASSERT_DISABLED
2141 LayerListMutationDetector mutationChecker(m_stackingNode.get());
2144 RenderLayerStackingNodeIterator iterator(*m_stackingNode, childrenToVisit);
2145 while (RenderLayerStackingNode* child = iterator.next()) {
2146 RenderLayer* childLayer = child->layer();
2148 // Squashed RenderLayers should not paint into their ancestor.
2149 if (childLayer->compositingState() == PaintsIntoGroupedBacking)
2152 if (!childLayer->isPaginated())
2153 childLayer->paintLayer(context, paintingInfo, paintFlags);
2155 paintPaginatedChildLayer(childLayer, context, paintingInfo, paintFlags);
2159 void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, RenderRegion* region, const LayoutRect& dirtyRect,
2160 ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const LayoutPoint* offsetFromRoot,
2161 const LayoutSize& subPixelAccumulation, const LayoutRect* layerBoundingBox)
2163 if (!enclosingPaginationLayer() || hasTransform()) {
2164 // For unpaginated layers, there is only one fragment.
2165 LayerFragment fragment;
2166 ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip, subPixelAccumulation);
2167 clipper().calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFromRoot);
2168 fragments.append(fragment);
2172 // Compute our offset within the enclosing pagination layer.
2173 LayoutPoint offsetWithinPaginatedLayer;
2174 convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginatedLayer);
2176 // Calculate clip rects relative to the enclosingPaginationLayer. The purpose of this call is to determine our bounds clipped to intermediate
2177 // 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.
2178 ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
2179 LayoutRect layerBoundsInFlowThread;
2180 ClipRect backgroundRectInFlowThread;
2181 ClipRect foregroundRectInFlowThread;
2182 ClipRect outlineRectInFlowThread;
2183 clipper().calculateRects(paginationClipRectsContext, PaintInfo::infiniteRect(), layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread,
2184 outlineRectInFlowThread, &offsetWithinPaginatedLayer);
2186 // Take our bounding box within the flow thread and clip it.
2187 LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : boundingBox(enclosingPaginationLayer(), 0, &offsetWithinPaginatedLayer);
2188 layerBoundingBoxInFlowThread.intersect(backgroundRectInFlowThread.rect());
2190 // Shift the dirty rect into flow thread coordinates.
2191 LayoutPoint offsetOfPaginationLayerFromRoot;
2192 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
2193 LayoutRect dirtyRectInFlowThread(dirtyRect);
2194 dirtyRectInFlowThread.moveBy(-offsetOfPaginationLayerFromRoot);
2196 // Tell the flow thread to collect the fragments. We pass enough information to create a minimal number of fragments based off the pages/columns
2197 // that intersect the actual dirtyRect as well as the pages/columns that intersect our layer's bounding box.
2198 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer());
2199 enclosingFlowThread->collectLayerFragments(fragments, layerBoundingBoxInFlowThread, dirtyRectInFlowThread);
2201 if (fragments.isEmpty())
2204 // Get the parent clip rects of the pagination layer, since we need to intersect with that when painting column contents.
2205 ClipRect ancestorClipRect = dirtyRect;
2206 if (enclosingPaginationLayer()->parent()) {
2207 ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
2208 ancestorClipRect = enclosingPaginationLayer()->clipper().backgroundClipRect(clipRectsContext);
2209 ancestorClipRect.intersect(dirtyRect);
2212 for (size_t i = 0; i < fragments.size(); ++i) {
2213 LayerFragment& fragment = fragments.at(i);
2215 // Set our four rects with all clipping applied that was internal to the flow thread.
2216 fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread);
2218 // Shift to the root-relative physical position used when painting the flow thread in this fragment.
2219 fragment.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
2221 // Intersect the fragment with our ancestor's background clip so that e.g., columns in an overflow:hidden block are
2222 // properly clipped by the overflow.
2223 fragment.intersect(ancestorClipRect.rect());
2225 // Now intersect with our pagination clip. This will typically mean we're just intersecting the dirty rect with the column
2226 // clip, so the column clip ends up being all we apply.
2227 fragment.intersect(fragment.paginationClip);
2231 void RenderLayer::updatePaintingInfoForFragments(LayerFragments& fragments, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags localPaintFlags,
2232 bool shouldPaintContent, const LayoutPoint* offsetFromRoot)
2234 ASSERT(offsetFromRoot);
2235 for (size_t i = 0; i < fragments.size(); ++i) {
2236 LayerFragment& fragment = fragments.at(i);
2237 fragment.shouldPaintContent = shouldPaintContent;
2238 if (this != localPaintingInfo.rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents)) {
2239 LayoutPoint newOffsetFromRoot = *offsetFromRoot + fragment.paginationOffset;
2240 fragment.shouldPaintContent &= intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLayer, &newOffsetFromRoot);
2245 void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2247 LayerFragments enclosingPaginationFragments;
2248 LayoutPoint offsetOfPaginationLayerFromRoot;
2249 LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintingInfo.paintBehavior);
2250 enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.region, paintingInfo.paintDirtyRect,
2251 (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
2252 (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetOfPaginationLayerFromRoot, paintingInfo.subPixelAccumulation, &transformedExtent);
2254 for (size_t i = 0; i < enclosingPaginationFragments.size(); ++i) {
2255 const LayerFragment& fragment = enclosingPaginationFragments.at(i);
2257 // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and
2258 // the enclosing pagination layer.
2259 LayoutRect clipRect = fragment.backgroundRect.rect();
2261 // Now compute the clips within a given fragment
2262 if (parent() != enclosingPaginationLayer()) {
2263 enclosingPaginationLayer()->convertToLayerCoords(paintingInfo.rootLayer, offsetOfPaginationLayerFromRoot);
2265 ClipRectsContext clipRectsContext(enclosingPaginationLayer(), paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
2266 IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
2267 LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect();
2268 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
2269 clipRect.intersect(parentClipRect);
2272 parent()->clipToRect(paintingInfo.rootLayer, context, paintingInfo.paintDirtyRect, clipRect);
2273 paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
2274 parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
2278 static inline LayoutSize subPixelAccumulationIfNeeded(const LayoutSize& subPixelAccumulation, CompositingState compositingState)
2280 // Only apply the sub-pixel accumulation if we don't paint into our own backing layer, otherwise the position
2281 // of the renderer already includes any sub-pixel offset.
2282 if (compositingState == PaintsIntoOwnBacking)
2283 return LayoutSize();
2284 return subPixelAccumulation;
2287 void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
2288 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
2289 RenderObject* paintingRootForRenderer)
2291 for (size_t i = 0; i < layerFragments.size(); ++i) {
2292 const LayerFragment& fragment = layerFragments.at(i);
2293 if (!fragment.shouldPaintContent)
2296 // Begin transparency layers lazily now that we know we have to paint something.
2297 if (haveTransparency || paintsWithBlendMode())
2298 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.paintBehavior);
2300 if (localPaintingInfo.clipToDirtyRect) {
2301 // Paint our background first, before painting any child layers.
2302 // Establish the clip used to paint our background.
2303 clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
2306 // Paint the background.
2307 // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
2308 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
2309 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2311 if (localPaintingInfo.clipToDirtyRect)
2312 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2316 void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
2317 const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
2318 RenderObject* paintingRootForRenderer, bool selectionOnly, bool forceBlackText)
2320 // Begin transparency if we have something to paint.
2321 if (haveTransparency || paintsWithBlendMode()) {
2322 for (size_t i = 0; i < layerFragments.size(); ++i) {
2323 const LayerFragment& fragment = layerFragments.at(i);
2324 if (fragment.shouldPaintContent && !fragment.foregroundRect.isEmpty()) {
2325 beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.paintBehavior);
2331 PaintBehavior localPaintBehavior = forceBlackText ? (PaintBehavior)PaintBehaviorForceBlackText : paintBehavior;
2333 // Optimize clipping for the single fragment case.
2334 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
2336 clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
2338 // We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for
2339 // interleaving of the fragments to work properly.
2340 paintForegroundForFragmentsWithPhase(selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, layerFragments,
2341 context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2343 if (!selectionOnly) {
2344 paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2345 paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2346 paintForegroundForFragmentsWithPhase(PaintPhaseChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
2350 restoreClip(context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
2353 void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext* context,
2354 const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
2356 bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() > 1;
2358 for (size_t i = 0; i < layerFragments.size(); ++i) {
2359 const LayerFragment& fragment = layerFragments.at(i);
2360 if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty())
2364 clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
2366 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
2367 if (phase == PaintPhaseForeground)
2368 paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
2369 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2372 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
2376 void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2377 PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
2379 for (size_t i = 0; i < layerFragments.size(); ++i) {
2380 const LayerFragment& fragment = layerFragments.at(i);
2381 if (fragment.outlineRect.isEmpty())
2384 // Paint our own outline
2385 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
2386 clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.outlineRect, DoNotIncludeSelfForBorderRadius);
2387 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2388 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect);
2392 void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2393 RenderObject* paintingRootForRenderer)
2395 for (size_t i = 0; i < layerFragments.size(); ++i) {
2396 const LayerFragment& fragment = layerFragments.at(i);
2397 if (!fragment.shouldPaintContent)
2400 if (localPaintingInfo.clipToDirtyRect)
2401 clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
2404 // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
2405 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
2406 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2408 if (localPaintingInfo.clipToDirtyRect)
2409 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2413 void RenderLayer::paintChildClippingMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
2414 RenderObject* paintingRootForRenderer)
2416 for (size_t i = 0; i < layerFragments.size(); ++i) {
2417 const LayerFragment& fragment = layerFragments.at(i);
2418 if (!fragment.shouldPaintContent)
2421 if (localPaintingInfo.clipToDirtyRect)
2422 clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
2424 // Paint the the clipped mask.
2425 PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseClippingMask, PaintBehaviorNormal, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
2426 renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState())));
2428 if (localPaintingInfo.clipToDirtyRect)
2429 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
2433 void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo)
2435 for (size_t i = 0; i < layerFragments.size(); ++i) {
2436 const LayerFragment& fragment = layerFragments.at(i);
2437 clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2438 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea())
2439 scrollableArea->paintOverflowControls(context, roundedIntPoint(toPoint(fragment.layerBounds.location() - renderBoxLocation() + subPixelAccumulationIfNeeded(localPaintingInfo.subPixelAccumulation, compositingState()))), pixelSnappedIntRect(fragment.backgroundRect.rect()), true);
2440 restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
2444 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
2446 // We need to do multiple passes, breaking up our child layer into strips.
2447 Vector<RenderLayer*> columnLayers;
2448 RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContainerNode();
2449 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
2450 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
2451 columnLayers.append(curr);
2452 if (curr->stackingNode() == ancestorNode)
2456 // It is possible for paintLayer() to be called after the child layer ceases to be paginated but before
2457 // updateLayerPositions() is called and resets the isPaginated() flag, see <rdar://problem/10098679>.
2458 // If this is the case, just bail out, since the upcoming call to updateLayerPositions() will repaint the layer.
2459 if (!columnLayers.size())
2462 paintChildLayerIntoColumns(childLayer, context, paintingInfo, paintFlags, columnLayers, columnLayers.size() - 1);
2465 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo,
2466 PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
2468 RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
2470 ASSERT(columnBlock && columnBlock->hasColumns());
2471 if (!columnBlock || !columnBlock->hasColumns())
2474 LayoutPoint layerOffset;
2475 // FIXME: It looks suspicious to call convertToLayerCoords here
2476 // as canUseConvertToLayerCoords is true for this layer.
2477 columnBlock->layer()->convertToLayerCoords(paintingInfo.rootLayer, layerOffset);
2479 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
2481 ColumnInfo* colInfo = columnBlock->columnInfo();
2482 unsigned colCount = columnBlock->columnCount(colInfo);
2483 LayoutUnit currLogicalTopOffset = 0;
2484 for (unsigned i = 0; i < colCount; i++) {
2485 // For each rect, we clip to the rect, and then we adjust our coords.
2486 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
2487 columnBlock->flipForWritingMode(colRect);
2488 LayoutUnit logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent();
2491 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2492 offset = LayoutSize(logicalLeftOffset, currLogicalTopOffset);
2494 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
2496 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2497 offset = LayoutSize(currLogicalTopOffset, logicalLeftOffset);
2499 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
2502 colRect.moveBy(layerOffset);
2504 LayoutRect localDirtyRect(paintingInfo.paintDirtyRect);
2505 localDirtyRect.intersect(colRect);
2507 if (!localDirtyRect.isEmpty()) {
2508 GraphicsContextStateSaver stateSaver(*context);
2510 // Each strip pushes a clip, since column boxes are specified as being
2511 // like overflow:hidden.
2512 context->clip(pixelSnappedIntRect(colRect));
2515 // Apply a translation transform to change where the layer paints.
2516 TransformationMatrix oldTransform;
2517 bool oldHasTransform = childLayer->transform();
2518 if (oldHasTransform)
2519 oldTransform = *childLayer->transform();
2520 TransformationMatrix newTransform(oldTransform);
2521 newTransform.translateRight(roundToInt(offset.width()), roundToInt(offset.height()));
2523 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
2525 LayerPaintingInfo localPaintingInfo(paintingInfo);
2526 localPaintingInfo.paintDirtyRect = localDirtyRect;
2527 childLayer->paintLayer(context, localPaintingInfo, paintFlags);
2529 if (oldHasTransform)
2530 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
2532 childLayer->m_transform.clear();
2534 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
2535 // This involves subtracting out the position of the layer in our current coordinate space.
2536 LayoutPoint childOffset;
2537 columnLayers[colIndex - 1]->convertToLayerCoords(paintingInfo.rootLayer, childOffset);
2538 TransformationMatrix transform;
2539 transform.translateRight(roundToInt(childOffset.x() + offset.width()), roundToInt(childOffset.y() + offset.height()));
2541 // Apply the transform.
2542 context->concatCTM(transform.toAffineTransform());
2544 // Now do a paint with the root layer shifted to be the next multicol block.
2545 LayerPaintingInfo columnPaintingInfo(paintingInfo);
2546 columnPaintingInfo.rootLayer = columnLayers[colIndex - 1];
2547 columnPaintingInfo.paintDirtyRect = transform.inverse().mapRect(localDirtyRect);
2548 paintChildLayerIntoColumns(childLayer, context, columnPaintingInfo, paintFlags, columnLayers, colIndex - 1);
2552 // Move to the next position.
2553 LayoutUnit blockDelta = isHorizontal ? colRect.height() : colRect.width();
2554 if (columnBlock->style()->isFlippedBlocksWritingMode())
2555 currLogicalTopOffset += blockDelta;
2557 currLogicalTopOffset -= blockDelta;
2561 static inline LayoutRect frameVisibleRect(RenderObject* renderer)
2563 FrameView* frameView = renderer->document().view();
2565 return LayoutRect();
2567 return frameView->visibleContentRect();
2570 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
2572 return hitTest(request, result.hitTestLocation(), result);
2575 bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation& hitTestLocation, HitTestResult& result)
2577 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
2579 // RenderView should make sure to update layout before entering hit testing
2580 ASSERT(!renderer()->frame()->view()->layoutPending());
2581 ASSERT(!renderer()->document().renderer()->needsLayout());
2583 LayoutRect hitTestArea = isOutOfFlowRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect();
2584 if (!request.ignoreClipping())
2585 hitTestArea.intersect(frameVisibleRect(renderer()));
2587 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestLocation, false);
2589 // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
2590 // return ourselves. We do this so mouse events continue getting delivered after a drag has
2591 // exited the WebView, and so hit testing over a scrollbar hits the content document.
2592 if (!request.isChildFrameHitTest() && (request.active() || request.release()) && isRootLayer()) {
2593 renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(hitTestLocation.point()));
2598 // Now determine if the result is inside an anchor - if the urlElement isn't already set.
2599 Node* node = result.innerNode();
2600 if (node && !result.URLElement())
2601 result.setURLElement(toElement(node->enclosingLinkEventParentOrSelf()));
2603 // Now return whether we were inside this layer (this will always be true for the root
2608 Node* RenderLayer::enclosingElement() const
2610 for (RenderObject* r = renderer(); r; r = r->parent()) {
2611 if (Node* e = r->node())
2614 ASSERT_NOT_REACHED();
2618 bool RenderLayer::isInTopLayer() const
2620 Node* node = renderer()->node();
2621 return node && node->isElementNode() && toElement(node)->isInTopLayer();
2624 bool RenderLayer::isInTopLayerSubtree() const
2626 for (const RenderLayer* layer = this; layer; layer = layer->parent()) {
2627 if (layer->isInTopLayer())
2633 // Compute the z-offset of the point in the transformState.
2634 // This is effectively projecting a ray normal to the plane of ancestor, finding where that
2635 // ray intersects target, and computing the z delta between those two points.
2636 static double computeZOffset(const HitTestingTransformState& transformState)
2638 // We got an affine transform, so no z-offset
2639 if (transformState.m_accumulatedTransform.isAffine())
2642 // Flatten the point into the target plane
2643 FloatPoint targetPoint = transformState.mappedPoint();
2645 // Now map the point back through the transform, which computes Z.
2646 FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
2647 return backmappedPoint.z();
2650 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
2651 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
2652 const HitTestingTransformState* containerTransformState,
2653 const LayoutPoint& translationOffset) const
2655 RefPtr<HitTestingTransformState> transformState;
2657 if (containerTransformState) {
2658 // If we're already computing transform state, then it's relative to the container (which we know is non-null).
2659 transformState = HitTestingTransformState::create(*containerTransformState);
2660 convertToLayerCoords(containerLayer, offset);
2662 // If this is the first time we need to make transform state, then base it off of hitTestLocation,
2663 // which is relative to rootLayer.
2664 transformState = HitTestingTransformState::create(hitTestLocation.transformedPoint(), hitTestLocation.transformedRect(), FloatQuad(hitTestRect));
2665 convertToLayerCoords(rootLayer, offset);
2667 offset.moveBy(translationOffset);
2669 RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
2670 if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
2671 TransformationMatrix containerTransform;
2672 renderer()->getTransformFromContainer(containerRenderer, toLayoutSize(offset), containerTransform);
2673 transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
2675 transformState->translate(offset.x(), offset.y(), HitTestingTransformState::AccumulateTransform);
2678 return transformState;
2682 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
2687 // The hit layer is depth-sorting with other layers, so just say that it was hit.
2691 // We need to look at z-depth to decide if this layer was hit.
2693 ASSERT(transformState);
2694 // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
2695 double childZOffset = computeZOffset(*transformState);
2696 if (childZOffset > *zOffset) {
2697 *zOffset = childZOffset;
2706 // hitTestLocation and hitTestRect are relative to rootLayer.
2707 // A 'flattening' layer is one preserves3D() == false.
2708 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
2709 // transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the containing flattening layer.
2710 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
2712 // If zOffset is non-null (which indicates that the caller wants z offset information),
2713 // *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
2714 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
2715 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, bool appliedTransform,
2716 const HitTestingTransformState* transformState, double* zOffset)
2718 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
2721 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
2723 // Apply a transform if we have one.
2724 if (transform() && !appliedTransform) {
2725 if (enclosingPaginationLayer())
2726 return hitTestTransformedLayerInFragments(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
2728 // Make sure the parent's clip rects have been calculated.
2730 ClipRectsContext clipRectsContext(rootLayer, hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
2731 ClipRect clipRect = clipper().backgroundClipRect(clipRectsContext);
2732 // Go ahead and test the enclosing clip now.
2733 if (!clipRect.intersects(hitTestLocation))
2737 return hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
2740 // Ensure our lists and 3d status are up-to-date.
2741 m_stackingNode->updateLayerListsIfNeeded();
2742 update3DTransformedDescendantStatus();
2744 RefPtr<HitTestingTransformState> localTransformState;
2745 if (appliedTransform) {
2746 // We computed the correct state in the caller (above code), so just reference it.
2747 ASSERT(transformState);
2748 localTransformState = const_cast<HitTestingTransformState*>(transformState);
2749 } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
2750 // We need transform state for the first time, or to offset the container state, so create it here.
2751 localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState);
2754 // Check for hit test on backface if backface-visibility is 'hidden'
2755 if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
2756 TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
2757 // If the z-vector of the matrix is negative, the back is facing towards the viewer.
2758 if (invertedMatrix.m33() < 0)
2762 RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
2763 if (localTransformState && !preserves3D()) {
2764 // Keep a copy of the pre-flattening state, for computing z-offsets for the container
2765 unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
2766 // This layer is flattening, so flatten the state passed to descendants.
2767 localTransformState->flatten();
2770 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
2772 double localZOffset = -numeric_limits<double>::infinity();
2773 double* zOffsetForDescendantsPtr = 0;
2774 double* zOffsetForContentsPtr = 0;
2776 bool depthSortDescendants = false;
2777 if (preserves3D()) {
2778 depthSortDescendants = true;
2779 // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
2780 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
2781 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
2782 } else if (m_has3DTransformedDescendant) {
2783 // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
2784 depthSortDescendants = true;
2785 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
2786 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
2787 } else if (zOffset) {
2788 zOffsetForDescendantsPtr = 0;
2789 // Container needs us to give back a z offset for the hit layer.
2790 zOffsetForContentsPtr = zOffset;
2793 // This variable tracks which layer the mouse ends up being inside.
2794 RenderLayer* candidateLayer = 0;
2796 // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
2797 RenderLayer* hitLayer = hitTestChildren(PositiveZOrderChildren, rootLayer, request, result, hitTestRect, hitTestLocation,
2798 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
2800 if (!depthSortDescendants)
2802 candidateLayer = hitLayer;
2805 // Now check our overflow objects.
2806 hitLayer = hitTestChildren(NormalFlowChildren, rootLayer, request, result, hitTestRect, hitTestLocation,
2807 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
2809 if (!depthSortDescendants)
2811 candidateLayer = hitLayer;
2814 // Collect the fragments. This will compute the clip rectangles for each layer fragment.
2815 LayerFragments layerFragments;
2816 collectFragments(layerFragments, rootLayer, hitTestLocation.region(), hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize);
2818 if (m_scrollableArea && m_scrollableArea->hitTestResizerInFragments(layerFragments, hitTestLocation)) {
2819 renderer()->updateHitTestResult(result, hitTestLocation.point());
2823 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. Check
2824 // every fragment in reverse order.
2825 if (isSelfPaintingLayer()) {
2826 // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
2827 HitTestResult tempResult(result.hitTestLocation());
2828 bool insideFragmentForegroundRect = false;
2829 if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestDescendants, insideFragmentForegroundRect)
2830 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
2831 if (result.isRectBasedTest())
2832 result.append(tempResult);
2834 result = tempResult;
2835 if (!depthSortDescendants)
2837 // Foreground can depth-sort with descendant layers, so keep this as a candidate.
2838 candidateLayer = this;
2839 } else if (insideFragmentForegroundRect && result.isRectBasedTest())
2840 result.append(tempResult);
2843 // Now check our negative z-index children.
2844 hitLayer = hitTestChildren(NegativeZOrderChildren, rootLayer, request, result, hitTestRect, hitTestLocation,
2845 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
2847 if (!depthSortDescendants)
2849 candidateLayer = hitLayer;
2852 // If we found a layer, return. Child layers, and foreground always render in front of background.
2854 return candidateLayer;
2856 if (isSelfPaintingLayer()) {
2857 HitTestResult tempResult(result.hitTestLocation());
2858 bool insideFragmentBackgroundRect = false;
2859 if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestSelf, insideFragmentBackgroundRect)
2860 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
2861 if (result.isRectBasedTest())
2862 result.append(tempResult);
2864 result = tempResult;
2867 if (insideFragmentBackgroundRect && result.isRectBasedTest())
2868 result.append(tempResult);
2874 bool RenderLayer::hitTestContentsForFragments(const LayerFragments& layerFragments, const HitTestRequest& request, HitTestResult& result,
2875 const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter, bool& insideClipRect) const
2877 if (layerFragments.isEmpty())
2880 for (int i = layerFragments.size() - 1; i >= 0; --i) {
2881 const LayerFragment& fragment = layerFragments.at(i);
2882 if ((hitTestFilter == HitTestSelf && !fragment.backgroundRect.intersects(hitTestLocation))
2883 || (hitTestFilter == HitTestDescendants && !fragment.foregroundRect.intersects(hitTestLocation)))
2885 insideClipRect = true;
2886 if (hitTestContents(request, result, fragment.layerBounds, hitTestLocation, hitTestFilter))
2893 RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
2894 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
2896 LayerFragments enclosingPaginationFragments;
2897 LayoutPoint offsetOfPaginationLayerFromRoot;
2898 LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, RootOfTransparencyClipBox);
2899 enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestLocation.region(), hitTestRect,
2900 RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent);
2902 for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) {
2903 const LayerFragment& fragment = enclosingPaginationFragments.at(i);
2905 // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and
2906 // the enclosing pagination layer.
2907 LayoutRect clipRect = fragment.backgroundRect.rect();
2909 // Now compute the clips within a given fragment
2910 if (parent() != enclosingPaginationLayer()) {
2911 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
2913 ClipRectsContext clipRectsContext(enclosingPaginationLayer(), hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
2914 LayoutRect parentClipRect = clipper().backgroundClipRect(clipRectsContext).rect();
2915 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
2916 clipRect.intersect(parentClipRect);
2919 if (!hitTestLocation.intersects(clipRect))
2922 RenderLayer* hitLayer = hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation,
2923 transformState, zOffset, fragment.paginationOffset);
2931 RenderLayer* RenderLayer::hitTestLayerByApplyingTransform(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
2932 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
2933 const LayoutPoint& translationOffset)
2935 // Create a transform state to accumulate this transform.
2936 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, translationOffset);
2938 // If the transform can't be inverted, then don't hit test this layer at all.
2939 if (!newTransformState->m_accumulatedTransform.isInvertible())
2942 // Compute the point and the hit test rect in the coords of this layer by using the values
2943 // from the transformState, which store the point and quad in the coords of the last flattened
2944 // layer, and the accumulated transform which lets up map through preserve-3d layers.
2946 // We can't just map hitTestLocation and hitTestRect because they may have been flattened (losing z)
2947 // by our container.
2948 FloatPoint localPoint = newTransformState->mappedPoint();
2949 FloatQuad localPointQuad = newTransformState->mappedQuad();
2950 LayoutRect localHitTestRect = newTransformState->boundsOfMappedArea();
2951 HitTestLocation newHitTestLocation;
2952 if (hitTestLocation.isRectBasedTest())
2953 newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
2955 newHitTestLocation = HitTestLocation(localPoint);
2957 // Now do a hit test with the root layer shifted to be us.
2958 return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestLocation, true, newTransformState.get(), zOffset);
2961 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter) const
2963 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
2965 if (!renderer()->hitTest(request, result, hitTestLocation, toLayoutPoint(layerBounds.location() - renderBoxLocation()), hitTestFilter)) {
2966 // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
2967 // a rect-based test.
2968 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size()));
2972 // For positioned generated content, we might still not have a
2973 // node by the time we get to the layer level, since none of
2974 // the content in the layer has an element. So just walk up
2976 if (!result.innerNode() || !result.innerNonSharedNode()) {
2977 Node* e = enclosingElement();
2978 if (!result.innerNode())
2979 result.setInnerNode(e);
2980 if (!result.innerNonSharedNode())
2981 result.setInnerNonSharedNode(e);
2987 RenderLayer* RenderLayer::hitTestChildren(ChildrenIteration childrentoVisit, RenderLayer* rootLayer,
2988 const HitTestRequest& request, HitTestResult& result,
2989 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
2990 const HitTestingTransformState* transformState,
2991 double* zOffsetForDescendants, double* zOffset,
2992 const HitTestingTransformState* unflattenedTransformState,
2993 bool depthSortDescendants)
2995 if (!hasSelfPaintingLayerDescendant())
2998 RenderLayer* resultLayer = 0;
2999 RenderLayerStackingNodeReverseIterator iterator(*m_stackingNode, childrentoVisit);
3000 while (RenderLayerStackingNode* child = iterator.next()) {
3001 RenderLayer* childLayer = child->layer();
3002 RenderLayer* hitLayer = 0;
3003 HitTestResult tempResult(result.hitTestLocation());
3004 if (childLayer->isPaginated())
3005 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestLocation, transformState, zOffsetForDescendants);
3007 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants);
3009 // If it a rect-based test, we can safely append the temporary result since it might had hit
3010 // nodes but not necesserily had hitLayer set.
3011 if (result.isRectBasedTest())
3012 result.append(tempResult);
3014 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
3015 resultLayer = hitLayer;
3016 if (!result.isRectBasedTest())
3017 result = tempResult;
3018 if (!depthSortDescendants)
3026 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3027 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
3029 Vector<RenderLayer*> columnLayers;
3030 RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContainerNode();
3031 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
3032 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
3033 columnLayers.append(curr);
3034 if (curr->stackingNode() == ancestorNode)
3038 ASSERT(columnLayers.size());
3039 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset,
3040 columnLayers, columnLayers.size() - 1);
3043 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3044 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
3045 const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
3047 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
3049 ASSERT(columnBlock && columnBlock->hasColumns());
3050 if (!columnBlock || !columnBlock->hasColumns())
3053 LayoutPoint layerOffset;
3054 columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
3056 ColumnInfo* colInfo = columnBlock->columnInfo();
3057 int colCount = columnBlock->columnCount(colInfo);
3059 // We have to go backwards from the last column to the first.
3060 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
3061 LayoutUnit logicalLeft = columnBlock->logicalLeftOffsetForContent();
3062 LayoutUnit currLogicalTopOffset = 0;
3064 for (i = 0; i < colCount; i++) {
3065 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
3066 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width());
3067 if (columnBlock->style()->isFlippedBlocksWritingMode())
3068 currLogicalTopOffset += blockDelta;
3070 currLogicalTopOffset -= blockDelta;
3072 for (i = colCount - 1; i >= 0; i--) {
3073 // For each rect, we clip to the rect, and then we adjust our coords.
3074 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
3075 columnBlock->flipForWritingMode(colRect);
3076 LayoutUnit currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft;
3077 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.width());
3078 if (columnBlock->style()->isFlippedBlocksWritingMode())
3079 currLogicalTopOffset -= blockDelta;
3081 currLogicalTopOffset += blockDelta;
3085 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3086 offset = LayoutSize(currLogicalLeftOffset, currLogicalTopOffset);
3088 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
3090 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
3091 offset = LayoutSize(currLogicalTopOffset, currLogicalLeftOffset);
3093 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
3096 colRect.moveBy(layerOffset);
3098 LayoutRect localClipRect(hitTestRect);
3099 localClipRect.intersect(colRect);
3101 if (!localClipRect.isEmpty() && hitTestLocation.intersects(localClipRect)) {
3102 RenderLayer* hitLayer = 0;
3104 // Apply a translation transform to change where the layer paints.
3105 TransformationMatrix oldTransform;
3106 bool oldHasTransform = childLayer->transform();
3107 if (oldHasTransform)
3108 oldTransform = *childLayer->transform();
3109 TransformationMatrix newTransform(oldTransform);
3110 newTransform.translateRight(offset.width(), offset.height());
3112 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
3113 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestLocation, false, transformState, zOffset);
3114 if (oldHasTransform)
3115 childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
3117 childLayer->m_transform.clear();
3119 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
3120 // This involves subtracting out the position of the layer in our current coordinate space.
3121 RenderLayer* nextLayer = columnLayers[columnIndex - 1];
3122 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestLocation, transformState);
3123 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform);
3124 FloatPoint localPoint = newTransformState->mappedPoint();
3125 FloatQuad localPointQuad = newTransformState->mappedQuad();
3126 LayoutRect localHitTestRect = newTransformState->mappedArea().enclosingBoundingBox();
3127 HitTestLocation newHitTestLocation;
3128 if (hitTestLocation.isRectBasedTest())
3129 newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
3131 newHitTestLocation = HitTestLocation(localPoint);
3132 newTransformState->flatten();
3134 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestLocation,
3135 newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
3146 void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
3148 m_blockSelectionGapsBounds.unite(enclosingIntRect(bounds));
3151 void RenderLayer::clearBlockSelectionGapsBounds()
3153 m_blockSelectionGapsBounds = IntRect();
3154 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3155 child->clearBlockSelectionGapsBounds();
3158 void RenderLayer::repaintBlockSelectionGaps()
3160 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3161 child->repaintBlockSelectionGaps();
3163 if (m_blockSelectionGapsBounds.isEmpty())
3166 LayoutRect rect = m_blockSelectionGapsBounds;
3167 if (renderer()->hasOverflowClip()) {
3168 RenderBox* box = renderBox();
3169 rect.move(-box->scrolledContentOffset());
3170 if (!scrollableArea()->usesCompositedScrolling())
3171 rect.intersect(box->overflowClipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
3173 if (renderer()->hasClip())
3174 rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
3175 if (!rect.isEmpty())
3176 renderer()->repaintRectangle(rect);
3179 bool RenderLayer::hasBlockSelectionGapBounds() const
3181 return !m_blockSelectionGapsBounds.isEmpty();
3184 bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot) const
3186 // Always examine the canvas and the root.
3187 // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
3188 // paints the root's background.
3189 if (isRootLayer() || renderer()->isRoot())
3192 // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
3193 // can go ahead and return true.
3194 RenderView* view = renderer()->view();
3196 if (view && !renderer()->isRenderInline()) {
3197 LayoutRect b = layerBounds;
3198 b.inflate(view->maximalOutlineSize());
3199 if (b.intersects(damageRect))
3203 // Otherwise we need to compute the bounding box of this single layer and see if it intersects
3205 return boundingBox(rootLayer, 0, offsetFromRoot).intersects(damageRect);
3208 LayoutRect RenderLayer::localBoundingBox(CalculateLayerBoundsFlags flags) const
3210 // There are three special cases we need to consider.
3211 // (1) Inline Flows. For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
3212 // inline. In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the
3213 // line boxes of all three lines (including overflow on those lines).
3214 // (2) Left/Top Overflow. The width/height of layers already includes right/bottom overflow. However, in the case of left/top
3215 // overflow, we have to create a bounding box that will extend to include this overflow.
3216 // (3) Floats. When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
3217 // as part of our bounding box. We do this because we are the responsible layer for both hit testing and painting those
3220 if (renderer()->isInline() && renderer()->isRenderInline())
3221 result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
3222 else if (renderer()->isTableRow()) {
3223 // Our bounding box is just the union of all of our cells' border/overflow rects.
3224 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
3225 if (child->isTableCell()) {
3226 LayoutRect bbox = toRenderBox(child)->borderBoxRect();
3228 LayoutRect overflowRect = renderBox()->visualOverflowRect();
3229 if (bbox != overflowRect)
3230 result.unite(overflowRect);
3234 RenderBox* box = renderBox();
3236 if (!(flags & DontConstrainForMask) && box->hasMask()) {
3237 result = box->maskClipRect();
3238 box->flipForWritingMode(result); // The mask clip rect is in physical coordinates, so we have to flip, since localBoundingBox is not.
3240 LayoutRect bbox = box->borderBoxRect();
3242 LayoutRect overflowRect = box->visualOverflowRect();
3243 if (bbox != overflowRect)
3244 result.unite(overflowRect);
3248 RenderView* view = renderer()->view();
3251 result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
3256 LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags flags, const LayoutPoint* offsetFromRoot) const
3258 LayoutRect result = localBoundingBox(flags);
3259 if (renderer()->isBox())
3260 renderBox()->flipForWritingMode(result);
3262 renderer()->containingBlock()->flipForWritingMode(result);
3264 if (enclosingPaginationLayer() && (flags & UseFragmentBoxes)) {
3265 // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
3266 // get our true bounding box.
3267 LayoutPoint offsetWithinPaginationLayer;
3268 convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginationLayer);
3269 result.moveBy(offsetWithinPaginationLayer);
3271 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer());
3272 result = enclosingFlowThread->fragmentsBoundingBox(result);
3276 delta = *offsetFromRoot;
3278 enclosingPaginationLayer()->convertToLayerCoords(ancestorLayer, delta);
3279 result.moveBy(delta);
3285 delta = *offsetFromRoot;
3287 convertToLayerCoords(ancestorLayer, delta);
3289 result.moveBy(delta);
3293 IntRect RenderLayer::absoluteBoundingBox() const
3295 return pixelSnappedIntRect(boundingBox(root()));
3298 LayoutRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot, CalculateLayerBoundsFlags flags) const
3300 if (!isSelfPaintingLayer())
3301 return LayoutRect();
3303 // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
3304 if ((flags & ExcludeHiddenDescendants) && this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant())
3305 return LayoutRect();
3307 RenderLayerModelObject* renderer = this->renderer();
3309 if (isRootLayer()) {
3310 // The root layer is always just the size of the document.
3311 return renderer->view()->unscaledDocumentRect();
3314 LayoutRect boundingBoxRect = localBoundingBox(flags);
3316 if (renderer->isBox())
3317 toRenderBox(renderer)->flipForWritingMode(boundingBoxRect);
3319 renderer->containingBlock()->flipForWritingMode(boundingBoxRect);
3321 if (renderer->isRoot()) {
3322 // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
3323 // then it has to be big enough to cover the viewport in order to display the background. This is akin
3324 // to the code in RenderBox::paintRootBoxFillLayers().
3325 if (FrameView* frameView = renderer->view()->frameView()) {
3326 LayoutUnit contentsWidth = frameView->contentsWidth();
3327 LayoutUnit contentsHeight = frameView->contentsHeight();
3329 boundingBoxRect.setWidth(max(boundingBoxRect.width(), contentsWidth - boundingBoxRect.x()));
3330 boundingBoxRect.setHeight(max(boundingBoxRect.height(), contentsHeight - boundingBoxRect.y()));
3334 LayoutRect unionBounds = boundingBoxRect;
3335 bool shouldIncludeTransform = paintsWithTransform(PaintBehaviorNormal) || (transform() && flags & PretendLayerHasOwnBacking);
3337 if (flags & UseLocalClipRectIfPossible) {
3338 LayoutRect localClipRect = clipper().localClipRect();
3339 if (localClipRect != PaintInfo::infiniteRect()) {
3340 if ((flags & IncludeSelfTransform) && shouldIncludeTransform)
3341 localClipRect = transform()->mapRect(localClipRect);
3343 LayoutPoint ancestorRelOffset;
3344 convertToLayerCoords(ancestorLayer, ancestorRelOffset);
3345 localClipRect.moveBy(ancestorRelOffset);
3346 return localClipRect;
3350 // FIXME: should probably just pass 'flags' down to descendants.
3351 CalculateLayerBoundsFlags descendantFlags = DefaultCalculateLayerBoundsFlags | (flags & ExcludeHiddenDescendants) | (flags & IncludeCompositedDescendants);
3353 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded();
3355 if (m_reflectionInfo) {
3356 RenderLayer* reflectionLayer = m_reflectionInfo->reflectionLayer();
3357 if (!reflectionLayer->hasCompositedLayerMapping()) {
3358 LayoutRect childUnionBounds = reflectionLayer->calculateLayerBounds(this, 0, descendantFlags);
3359 unionBounds.unite(childUnionBounds);
3363 ASSERT(m_stackingNode->isStackingContainer() || !m_stackingNode->hasPositiveZOrderList());
3365 #if !ASSERT_DISABLED
3366 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this)->stackingNode());
3369 // FIXME: Descendants that are composited should not necessarily be skipped, if they don't paint into their own
3370 // separate backing. Instead, they ought to contribute to the bounds of the layer we're trying to compute.
3371 // This applies to all z-order lists below.
3372 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), AllChildren);
3373 while (RenderLayerStackingNode* node = iterator.next()) {
3374 // Node's compositing ancestor may have changed its draw content status
3375 // prior to updating its bounds. The requires-own-backing-store-for-ancestor-reasons
3376 // could be stale. Refresh them now.
3377 if (node->layer()->hasCompositedLayerMapping()) {
3378 RenderLayer* enclosingCompositingLayer = node->layer()->enclosingCompositingLayer(ExcludeSelf);
3379 node->layer()->compositedLayerMapping()->updateRequiresOwnBackingStoreForAncestorReasons(enclosingCompositingLayer);
3382 if (flags & IncludeCompositedDescendants || !node->layer()->hasCompositedLayerMapping()) {
3383 LayoutRect childUnionBounds = node->layer()->calculateLayerBounds(this, 0, descendantFlags);
3384 unionBounds.unite(childUnionBounds);
3388 // FIXME: We can optimize the size of the composited layers, by not enlarging
3389 // filtered areas with the outsets if we know that the filter is going to render in hardware.
3390 // https://bugs.webkit.org/show_bug.cgi?id=81239
3391 if (flags & IncludeLayerFilterOutsets)
3392 renderer->style()->filterOutsets().expandRect(unionBounds);
3394 if ((flags & IncludeSelfTransform) && shouldIncludeTransform) {
3395 TransformationMatrix* affineTrans = transform();
3396 boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
3397 unionBounds = affineTrans->mapRect(unionBounds);
3400 LayoutPoint ancestorRelOffset;
3402 ancestorRelOffset = *offsetFromRoot;
3404 convertToLayerCoords(ancestorLayer, ancestorRelOffset);
3405 unionBounds.moveBy(ancestorRelOffset);
3410 CompositingState RenderLayer::compositingState() const
3412 // This is computed procedurally so there is no redundant state variable that
3413 // can get out of sync from the real actual compositing state.
3415 if (m_groupedMapping) {
3416 ASSERT(compositor()->layerSquashingEnabled());
3417 ASSERT(!m_compositedLayerMapping);
3418 return PaintsIntoGroupedBacking;
3421 if (!m_compositedLayerMapping)
3422 return NotComposited;
3424 if (m_compositedLayerMapping && compositedLayerMapping()->paintsIntoCompositedAncestor())
3425 return HasOwnBackingButPaintsIntoAncestor;
3427 ASSERT(m_compositedLayerMapping);
3428 return PaintsIntoOwnBacking;
3431 CompositedLayerMappingPtr RenderLayer::ensureCompositedLayerMapping()
3433 if (!m_compositedLayerMapping) {
3434 m_compositedLayerMapping = adoptPtr(new CompositedLayerMapping(this));
3436 updateOrRemoveFilterEffectRenderer();
3438 if (RuntimeEnabledFeatures::cssCompositingEnabled())
3439 compositedLayerMapping()->setBlendMode(m_blendInfo.blendMode());
3441 return m_compositedLayerMapping.get();
3444 void RenderLayer::clearCompositedLayerMapping(bool layerBeingDestroyed)
3446 m_compositedLayerMapping.clear();
3448 if (!layerBeingDestroyed)
3449 updateOrRemoveFilterEffectRenderer();
3452 bool RenderLayer::hasCompositedMask() const
3454 return m_compositedLayerMapping && m_compositedLayerMapping->hasMaskLayer();
3457 bool RenderLayer::hasCompositedClippingMask() const
3459 return m_compositedLayerMapping && m_compositedLayerMapping->hasChildClippingMaskLayer();
3462 bool RenderLayer::clipsCompositingDescendantsWithBorderRadius() const
3464 RenderStyle* style = renderer()->style();
3468 return compositor()->clipsCompositingDescendants(this) && style->hasBorderRadius();
3471 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
3473 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || compositingState() != PaintsIntoOwnBacking);
3476 bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
3478 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
3481 if (paintsWithTransparency(PaintBehaviorNormal))
3484 // We can't use hasVisibleContent(), because that will be true if our renderer is hidden, but some child
3485 // is visible and that child doesn't cover the entire rect.
3486 if (renderer()->style()->visibility() != VISIBLE)
3489 if (paintsWithFilters() && renderer()->style()->filter().hasFilterThatAffectsOpacity())
3492 // FIXME: Handle simple transforms.
3493 if (paintsWithTransform(PaintBehaviorNormal))
3496 // FIXME: Remove this check.
3497 // This function should not be called when layer-lists are dirty.
3498 // It is somehow getting triggered during style update.
3499 if (m_stackingNode->zOrderListsDirty() || m_stackingNode->normalFlowListDirty())
3502 // FIXME: We currently only check the immediate renderer,
3503 // which will miss many cases.
3504 if (renderer()->backgroundIsKnownToBeOpaqueInRect(localRect))
3507 // We can't consult child layers if we clip, since they might cover
3508 // parts of the rect that are clipped out.
3509 if (renderer()->hasOverflowClip())
3512 return childBackgroundIsKnownToBeOpaqueInRect(localRect);
3515 bool RenderLayer::childBackgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
3517 RenderLayerStackingNodeReverseIterator revertseIterator(*m_stackingNode, PositiveZOrderChildren | NormalFlowChildren | NegativeZOrderChildren);
3518 while (RenderLayerStackingNode* child = revertseIterator.next()) {
3519 const RenderLayer* childLayer = child->layer();
3520 if (childLayer->hasCompositedLayerMapping())
3523 if (!childLayer->canUseConvertToLayerCoords())
3526 LayoutPoint childOffset;
3527 LayoutRect childLocalRect(localRect);
3528 childLayer->convertToLayerCoords(this, childOffset);
3529 childLocalRect.moveBy(-childOffset);
3531 if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
3537 void RenderLayer::setParent(RenderLayer* parent)
3539 if (parent == m_parent)
3542 if (m_parent && !renderer()->documentBeingDestroyed())
3543 compositor()->layerWillBeRemoved(m_parent, this);
3547 if (m_parent && !renderer()->documentBeingDestroyed())
3548 compositor()->layerWasAdded(m_parent, this);
3551 bool RenderLayer::shouldBeSelfPaintingLayer() const
3553 return !m_isOverflowOnlyLayer
3554 || (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars())
3555 || needsCompositedScrolling();
3558 void RenderLayer::updateSelfPaintingLayer()
3560 bool isSelfPaintingLayer = this->shouldBeSelfPaintingLayer();
3561 if (this->isSelfPaintingLayer() == isSelfPaintingLayer)
3564 m_isSelfPaintingLayer = isSelfPaintingLayer;
3567 if (isSelfPaintingLayer)
3568 parent()->setAncestorChainHasSelfPaintingLayerDescendant();
3570 parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
3573 bool RenderLayer::hasNonEmptyChildRenderers() const
3575 // Some HTML can cause whitespace text nodes to have renderers, like:
3579 // so test for 0x0 RenderTexts here
3580 for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
3581 if (!child->hasLayer()) {
3582 if (child->isRenderInline() || !child->isBox())
3585 if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
3592 static bool hasBoxDecorations(const RenderStyle* style)
3594 return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
3597 bool RenderLayer::hasBoxDecorationsOrBackground() const
3599 return hasBoxDecorations(renderer()->style()) || renderer()->hasBackground();
3602 bool RenderLayer::hasVisibleBoxDecorations() const
3604 if (!hasVisibleContent())
3607 return hasBoxDecorationsOrBackground() || hasOverflowControls();
3610 bool RenderLayer::isVisuallyNonEmpty() const
3612 ASSERT(!m_visibleDescendantStatusDirty);
3614 if (hasVisibleContent() && hasNonEmptyChildRenderers())
3617 if (renderer()->isReplaced() || renderer()->hasMask())
3620 if (hasVisibleBoxDecorations())
3626 void RenderLayer::updateVisibilityAfterStyleChange(const RenderStyle* oldStyle)
3628 if (!oldStyle || (oldStyle->visibility() != renderer()->style()->visibility()))
3629 compositor()->setNeedsUpdateCompositingRequirementsState();
3632 void RenderLayer::updateOutOfFlowPositioned(const RenderStyle* oldStyle)
3634 if (oldStyle && (renderer()->style()->position() == oldStyle->position()))
3637 bool wasOutOfFlowPositioned = oldStyle && (oldStyle->position() == AbsolutePosition || oldStyle->position() == FixedPosition);
3638 bool isOutOfFlowPositioned = renderer()->isOutOfFlowPositioned();
3639 if (!wasOutOfFlowPositioned && !isOutOfFlowPositioned)
3642 // Even if the layer remains out-of-flow, a change to this property
3643 // will likely change its containing block. We must clear these bits
3644 // so that they can be set properly by the RenderLayerCompositor.
3645 for (RenderLayer* ancestor = parent(); ancestor; ancestor = ancestor->parent())
3646 ancestor->setHasUnclippedDescendant(false);
3648 // Ensures that we reset the above bits correctly.
3649 compositor()->setNeedsUpdateCompositingRequirementsState();
3651 if (wasOutOfFlowPositioned && isOutOfFlowPositioned)
3654 if (isOutOfFlowPositioned) {
3655 setAncestorChainHasOutOfFlowPositionedDescendant();
3656 compositor()->addOutOfFlowPositionedLayer(this);
3658 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
3659 compositor()->removeOutOfFlowPositionedLayer(this);
3661 // We need to reset the isUnclippedDescendant bit here because normally
3662 // the "unclipped-ness" property is only updated in
3663 // RenderLayerCompositor::updateCompositingRequirementsState(). However,
3664 // it is only updated for layers which are known to be out of flow.
3665 // Since this is no longer out of flow, we have to explicitly ensure
3666 // that it doesn't think it is unclipped.
3667 setIsUnclippedDescendant(false);
3671 static bool hasOrHadFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
3674 return (oldStyle && oldStyle->hasFilter()) || newStyle->hasFilter();
3677 inline bool RenderLayer::needsCompositingLayersRebuiltForClip(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
3680 return oldStyle && (oldStyle->clip() != newStyle->clip() || oldStyle->hasClip() != newStyle->hasClip());
3683 inline bool RenderLayer::needsCompositingLayersRebuiltForOverflow(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
3686 return !hasCompositedLayerMapping() && oldStyle && (oldStyle->overflowX() != newStyle->overflowX()) && m_stackingNode->ancestorStackingContainerNode()->layer()->hasCompositingDescendant();
3689 inline bool RenderLayer::needsCompositingLayersRebuiltForFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle, bool didPaintWithFilters) const
3691 if (!hasOrHadFilters(oldStyle, newStyle))
3694 if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()
3695 ? hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter)
3696 : renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter)) {
3698 // When the compositor is performing the filter animation, we shouldn't touch the compositing layers.
3699 // All of the layers above us should have been promoted to compositing layers already.
3703 FilterOutsets newOutsets = newStyle->filterOutsets();
3704 if (oldStyle && (oldStyle->filterOutsets() != newOutsets)) {
3705 // When filter outsets change, we need to:
3706 // (1) Recompute the overlap map to promote the correct layers to composited layers.
3707 // (2) Update the composited layer bounds (and child GraphicsLayer positions) on platforms
3708 // whose compositors can't compute their own filter outsets.
3712 #if HAVE(COMPOSITOR_FILTER_OUTSETS)
3713 if ((didPaintWithFilters != paintsWithFilters()) && !newOutsets.isZero()) {
3714 // When the layer used to paint filters in software and now paints filters in the
3715 // compositor, the compositing layer bounds need to change from including filter outsets to
3716 // excluding filter outsets, on platforms whose compositors compute their own outsets.
3717 // Similarly for the reverse change from compositor-painted to software-painted filters.
3725 inline bool RenderLayer::needsCompositingLayersRebuiltForBlending(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
3728 if (!hasCompositedLayerMapping())
3730 return (shouldIsolateCompositedDescendants() && !stackingNode()->isStackingContext())
3731 || (oldStyle && (oldStyle->hasBlendMode() != newStyle->hasBlendMode()));
3734 void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
3736 if (!hasOrHadFilters(oldStyle, newStyle))
3739 updateOrRemoveFilterClients();
3740 // During an accelerated animation, both WebKit and the compositor animate properties.
3741 // However, WebKit shouldn't ask the compositor to update its filters if the compositor is performing the animation.
3742 if (hasCompositedLayerMapping() && (RuntimeEnabledFeatures::webAnimationsCSSEnabled()
3743 ? !hasActiveAnimationsOnCompositor(*renderer(), CSSPropertyWebkitFilter)
3744 : !renderer()->animation().isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter)))
3745 compositedLayerMapping()->updateFilters(renderer()->style());
3746 updateOrRemoveFilterEffectRenderer();
3749 void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
3751 m_stackingNode->updateIsNormalFlowOnly();
3753 if (m_scrollableArea)
3754 m_scrollableArea->updateAfterStyleChange(oldStyle);
3755 m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle);
3756 updateVisibilityAfterStyleChange(oldStyle);
3757 // Overlay scrollbars can make this layer self-painting so we need
3758 // to recompute the bit once scrollbars have been updated.
3759 updateSelfPaintingLayer();
3760 updateOutOfFlowPositioned(oldStyle);
3762 updateReflectionInfo(oldStyle);
3764 if (RuntimeEnabledFeatures::cssCompositingEnabled())
3765 m_blendInfo.updateBlendMode();
3767 updateDescendantDependentFlags();
3770 bool didPaintWithFilters = false;
3772 if (paintsWithFilters())
3773 didPaintWithFilters = true;
3774 updateFilters(oldStyle, renderer()->style());
3776 const RenderStyle* newStyle = renderer()->style();
3777 if (compositor()->updateLayerCompositingState(this)
3778 || needsCompositingLayersRebuiltForClip(oldStyle, newStyle)
3779 || needsCompositingLayersRebuiltForOverflow(oldStyle, newStyle)
3780 || needsCompositingLayersRebuiltForFilters(oldStyle, newStyle, didPaintWithFilters)
3781 || needsCompositingLayersRebuiltForBlending(oldStyle, newStyle)) {
3782 compositor()->setCompositingLayersNeedRebuild();
3783 } else if (compositingState() == PaintsIntoOwnBacking || compositingState() == HasOwnBackingButPaintsIntoAncestor) {
3784 ASSERT(hasCompositedLayerMapping());
3785 compositedLayerMapping()->updateGraphicsLayerGeometry();
3786 } else if (compositingState() == PaintsIntoGroupedBacking) {
3787 ASSERT(compositor()->layerSquashingEnabled());
3788 ASSERT(groupedMapping());
3789 // updateGraphicsLayerGeometry() is called to update the squashingLayer in case its size/position has changed.
3790 // FIXME: Make sure to create a layout test that covers this scenario.
3791 // FIXME: It is not expected that any other layers on the compositedLayerMapping would change. we should
3792 // be able to just update the squashing layer only and save a lot of computation.
3793 groupedMapping()->updateGraphicsLayerGeometry();
3797 bool RenderLayer::scrollsOverflow() const
3799 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea())
3800 return scrollableArea->scrollsOverflow();
3805 FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
3807 const FilterOperations& filters = style->filter();
3808 if (filters.hasReferenceFilter()) {
3809 for (size_t i = 0; i < filters.size(); ++i) {
3810 FilterOperation* filterOperation = filters.operations().at(i).get();
3811 if (filterOperation->type() != FilterOperation::REFERENCE)
3813 ReferenceFilterOperation* referenceOperation = toReferenceFilterOperation(filterOperation);
3814 // FIXME: Cache the ReferenceFilter if it didn't change.
3815 RefPtr<ReferenceFilter> referenceFilter = ReferenceFilter::create();
3816 float zoom = style->effectiveZoom() * WebCore::deviceScaleFactor(renderer()->frame());
3817 referenceFilter->setAbsoluteTransform(AffineTransform().scale(zoom, zoom));
3818 referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referenceFilter.get(), renderer(), referenceFilter->sourceGraphic(),
3819 referenceOperation));
3820 referenceOperation->setFilter(referenceFilter.release());
3827 void RenderLayer::updateOrRemoveFilterClients()
3830 removeFilterInfoIfNeeded();
3834 if (renderer()->style()->filter().hasReferenceFilter())
3835 ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->filter());
3836 else if (hasFilterInfo())
3837 filterInfo()->removeReferenceFilterClients();
3840 void RenderLayer::updateOrRemoveFilterEffectRenderer()
3842 // FilterEffectRenderer is only used to render the filters in software mode,
3843 // so we always need to run updateOrRemoveFilterEffectRenderer after the composited
3844 // mode might have changed for this layer.
3845 if (!paintsWithFilters()) {
3846 // Don't delete the whole filter info here, because we might use it
3847 // for loading CSS shader files.
3848 if (RenderLayerFilterInfo* filterInfo = this->filterInfo())
3849 filterInfo->setRenderer(0);
3854 RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
3855 if (!filterInfo->renderer()) {
3856 RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create();
3857 filterRenderer->setIsAccelerated(renderer()->frame()->settings()->acceleratedFiltersEnabled());
3858 filterInfo->setRenderer(filterRenderer.release());
3860 // We can optimize away code paths in other places if we know that there are no software filters.
3861 renderer()->document().view()->setHasSoftwareFilters(true);
3864 // If the filter fails to build, remove it from the layer. It will still attempt to
3865 // go through regular processing (e.g. compositing), but never apply anything.
3866 if (!filterInfo->renderer()->build(renderer(), computeFilterOperations(renderer()->style())))
3867 filterInfo->setRenderer(0);
3870 void RenderLayer::filterNeedsRepaint()
3872 toElement(renderer()->node())->scheduleLayerUpdate();
3873 if (renderer()->view()) {
3874 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled() && renderer()->frameView()->isInPerformLayout())
3875 renderer()->setShouldDoFullRepaintAfterLayout(true);
3877 renderer()->repaint();
3881 void RenderLayer::addLayerHitTestRects(LayerHitTestRects& rects) const
3883 if (!size().isEmpty()) {
3884 Vector<LayoutRect> rect;
3886 if (renderBox() && renderBox()->scrollsOverflow()) {
3887 // For scrolling layers, rects are taken to be in the space of the contents.
3888 // We need to include both the entire contents, and also the bounding box
3889 // of the layer in the space of it's parent (eg. for border / scroll bars).
3890 rect.append(m_scrollableArea->overflowRect());
3891 rects.set(this, rect);
3892 if (const RenderLayer* parentLayer = parent()) {
3893 LayerHitTestRects::iterator iter = rects.find(parentLayer);
3894 if (iter == rects.end())
3895 iter = rects.add(parentLayer, Vector<LayoutRect>()).iterator;
3896 iter->value.append(boundingBox(parentLayer));
3899 rect.append(localBoundingBox());
3900 rects.set(this, rect);
3904 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3905 child->addLayerHitTestRects(rects);
3908 } // namespace WebCore
3911 void showLayerTree(const WebCore::RenderLayer* layer)
3916 if (WebCore::Frame* frame = layer->renderer()->frame()) {
3917 WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState);
3918 fprintf(stderr, "%s\n", output.utf8().data());
3922 void showLayerTree(const WebCore::RenderObject* renderer)
3926 showLayerTree(renderer->enclosingLayer());