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