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