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