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