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