Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: Source/core/rendering/RenderLayer.cpp

Issue 898783003: Move rendering/RenderLayer* to layout/ (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/rendering/RenderLayer.h ('k') | Source/core/rendering/RenderLayerClipper.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 US A
28 *
29 * Alternatively, the contents of this file may be used under the terms
30 * of either the Mozilla Public License Version 1.1, found at
31 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
32 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
33 * (the "GPL"), in which case the provisions of the MPL or the GPL are
34 * applicable instead of those above. If you wish to allow use of your
35 * version of this file only under the terms of one of those two
36 * licenses (the MPL or the GPL) and not to allow others to use your
37 * version of this file under the LGPL, indicate your decision by
38 * deletingthe provisions above and replace them with the notice and
39 * other provisions required by the MPL or the GPL, as the case may be.
40 * If you do not delete the provisions above, a recipient may use your
41 * version of this file under any of the LGPL, the MPL or the GPL.
42 */
43
44 #include "config.h"
45 #include "core/rendering/RenderLayer.h"
46
47 #include "core/CSSPropertyNames.h"
48 #include "core/HTMLNames.h"
49 #include "core/css/PseudoStyleRequest.h"
50 #include "core/dom/Document.h"
51 #include "core/dom/shadow/ShadowRoot.h"
52 #include "core/frame/DeprecatedScheduleStyleRecalcDuringLayout.h"
53 #include "core/frame/FrameView.h"
54 #include "core/frame/LocalFrame.h"
55 #include "core/html/HTMLFrameElement.h"
56 #include "core/layout/HitTestRequest.h"
57 #include "core/layout/HitTestResult.h"
58 #include "core/layout/HitTestingTransformState.h"
59 #include "core/layout/LayoutTreeAsText.h"
60 #include "core/layout/compositing/CompositedLayerMapping.h"
61 #include "core/layout/compositing/RenderLayerCompositor.h"
62 #include "core/page/Page.h"
63 #include "core/page/scrolling/ScrollingCoordinator.h"
64 #include "core/rendering/ColumnInfo.h"
65 #include "core/rendering/FilterEffectRenderer.h"
66 #include "core/rendering/RenderFlowThread.h"
67 #include "core/rendering/RenderGeometryMap.h"
68 #include "core/rendering/RenderInline.h"
69 #include "core/rendering/RenderPart.h"
70 #include "core/rendering/RenderReplica.h"
71 #include "core/rendering/RenderScrollbar.h"
72 #include "core/rendering/RenderScrollbarPart.h"
73 #include "core/rendering/RenderView.h"
74 #include "core/rendering/svg/ReferenceFilterBuilder.h"
75 #include "core/rendering/svg/RenderSVGRoot.h"
76 #include "platform/LengthFunctions.h"
77 #include "platform/Partitions.h"
78 #include "platform/RuntimeEnabledFeatures.h"
79 #include "platform/TraceEvent.h"
80 #include "platform/geometry/FloatPoint3D.h"
81 #include "platform/geometry/FloatRect.h"
82 #include "platform/geometry/TransformState.h"
83 #include "platform/graphics/filters/ReferenceFilter.h"
84 #include "platform/graphics/filters/SourceGraphic.h"
85 #include "platform/transforms/ScaleTransformOperation.h"
86 #include "platform/transforms/TransformationMatrix.h"
87 #include "platform/transforms/TranslateTransformOperation.h"
88 #include "public/platform/Platform.h"
89 #include "wtf/StdLibExtras.h"
90 #include "wtf/text/CString.h"
91
92 namespace blink {
93
94 namespace {
95
96 static CompositingQueryMode gCompositingQueryMode =
97 CompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases;
98
99 } // namespace
100
101 using namespace HTMLNames;
102
103 RenderLayer::RenderLayer(RenderLayerModelObject* renderer, LayerType type)
104 : m_layerType(type)
105 , m_hasSelfPaintingLayerDescendant(false)
106 , m_hasSelfPaintingLayerDescendantDirty(false)
107 , m_isRootLayer(renderer->isRenderView())
108 , m_visibleContentStatusDirty(true)
109 , m_hasVisibleContent(false)
110 , m_visibleDescendantStatusDirty(false)
111 , m_hasVisibleDescendant(false)
112 , m_hasVisibleNonLayerContent(false)
113 , m_isPaginated(false)
114 #if ENABLE(ASSERT)
115 , m_needsPositionUpdate(true)
116 #endif
117 , m_3DTransformedDescendantStatusDirty(true)
118 , m_has3DTransformedDescendant(false)
119 , m_containsDirtyOverlayScrollbars(false)
120 , m_hasFilterInfo(false)
121 , m_needsAncestorDependentCompositingInputsUpdate(true)
122 , m_needsDescendantDependentCompositingInputsUpdate(true)
123 , m_childNeedsCompositingInputsUpdate(true)
124 , m_hasCompositingDescendant(false)
125 , m_hasNonCompositedChild(false)
126 , m_shouldIsolateCompositedDescendants(false)
127 , m_lostGroupedMapping(false)
128 , m_renderer(renderer)
129 , m_parent(0)
130 , m_previous(0)
131 , m_next(0)
132 , m_first(0)
133 , m_last(0)
134 , m_staticInlinePosition(0)
135 , m_staticBlockPosition(0)
136 , m_enclosingPaginationLayer(0)
137 , m_potentialCompositingReasonsFromStyle(CompositingReasonNone)
138 , m_compositingReasons(CompositingReasonNone)
139 , m_groupedMapping(0)
140 , m_clipper(*renderer)
141 {
142 updateStackingNode();
143
144 m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
145
146 if (!renderer->slowFirstChild() && renderer->style()) {
147 m_visibleContentStatusDirty = false;
148 m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
149 }
150
151 updateScrollableArea();
152 }
153
154 RenderLayer::~RenderLayer()
155 {
156 if (renderer()->frame() && renderer()->frame()->page()) {
157 if (ScrollingCoordinator* scrollingCoordinator = renderer()->frame()->pa ge()->scrollingCoordinator())
158 scrollingCoordinator->willDestroyRenderLayer(this);
159 }
160
161 removeFilterInfoIfNeeded();
162
163 if (groupedMapping()) {
164 DisableCompositingQueryAsserts disabler;
165 groupedMapping()->removeRenderLayerFromSquashingGraphicsLayer(this);
166 setGroupedMapping(0);
167 }
168
169 // Child layers will be deleted by their corresponding render objects, so
170 // we don't need to delete them ourselves.
171
172 clearCompositedLayerMapping(true);
173
174 if (m_reflectionInfo)
175 m_reflectionInfo->destroy();
176 }
177
178 String RenderLayer::debugName() const
179 {
180 if (isReflection()) {
181 return renderer()->parent()->debugName() + " (reflection)";
182 }
183 return renderer()->debugName();
184 }
185
186 RenderLayerCompositor* RenderLayer::compositor() const
187 {
188 if (!renderer()->view())
189 return 0;
190 return renderer()->view()->compositor();
191 }
192
193 void RenderLayer::contentChanged(ContentChangeType changeType)
194 {
195 // updateLayerCompositingState will query compositingReasons for accelerated overflow scrolling.
196 // This is tripped by LayoutTests/compositing/content-changed-chicken-egg.ht ml
197 DisableCompositingQueryAsserts disabler;
198
199 if (changeType == CanvasChanged)
200 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositin gInputChange);
201
202 if (changeType == CanvasContextChanged) {
203 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositin gInputChange);
204
205 // Although we're missing test coverage, we need to call
206 // GraphicsLayer::setContentsToPlatformLayer with the new platform
207 // layer for this canvas.
208 // See http://crbug.com/349195
209 if (hasCompositedLayerMapping())
210 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerU pdateSubtree);
211 }
212
213 if (m_compositedLayerMapping)
214 m_compositedLayerMapping->contentChanged(changeType);
215 }
216
217 bool RenderLayer::paintsWithFilters() const
218 {
219 if (!renderer()->hasFilter())
220 return false;
221
222 // https://code.google.com/p/chromium/issues/detail?id=343759
223 DisableCompositingQueryAsserts disabler;
224 return !m_compositedLayerMapping || compositingState() != PaintsIntoOwnBacki ng;
225 }
226
227 LayoutSize RenderLayer::subpixelAccumulation() const
228 {
229 return m_subpixelAccumulation;
230 }
231
232 void RenderLayer::setSubpixelAccumulation(const LayoutSize& size)
233 {
234 m_subpixelAccumulation = size;
235 }
236
237 void RenderLayer::updateLayerPositionsAfterLayout()
238 {
239 TRACE_EVENT0("blink,benchmark", "RenderLayer::updateLayerPositionsAfterLayou t");
240
241 m_clipper.clearClipRectsIncludingDescendants();
242 updateLayerPositionRecursive();
243
244 {
245 // FIXME: Remove incremental compositing updates after fixing the chicke n/egg issues
246 // https://code.google.com/p/chromium/issues/detail?id=343756
247 DisableCompositingQueryAsserts disabler;
248 bool needsPaginationUpdate = isPaginated() || enclosingPaginationLayer() ;
249 updatePaginationRecursive(needsPaginationUpdate);
250 }
251 }
252
253 void RenderLayer::updateLayerPositionRecursive()
254 {
255 updateLayerPosition();
256
257 if (m_reflectionInfo)
258 m_reflectionInfo->reflection()->layout();
259
260 // FIXME: We should be able to remove this call because we don't care about
261 // any descendant-dependent flags, but code somewhere else is reading these
262 // flags and depending on us to update them.
263 updateDescendantDependentFlags();
264
265 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
266 child->updateLayerPositionRecursive();
267 }
268
269 void RenderLayer::updateHasSelfPaintingLayerDescendant() const
270 {
271 ASSERT(m_hasSelfPaintingLayerDescendantDirty);
272
273 m_hasSelfPaintingLayerDescendant = false;
274
275 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
276 if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendan t()) {
277 m_hasSelfPaintingLayerDescendant = true;
278 break;
279 }
280 }
281
282 m_hasSelfPaintingLayerDescendantDirty = false;
283 }
284
285 void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
286 {
287 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
288 layer->m_hasSelfPaintingLayerDescendantDirty = true;
289 // If we have reached a self-painting layer, we know our parent should h ave a self-painting descendant
290 // in this case, there is no need to dirty our ancestors further.
291 if (layer->isSelfPaintingLayer()) {
292 ASSERT(!parent() || parent()->m_hasSelfPaintingLayerDescendantDirty || parent()->m_hasSelfPaintingLayerDescendant);
293 break;
294 }
295 }
296 }
297
298 bool RenderLayer::scrollsWithViewport() const
299 {
300 return renderer()->style()->position() == FixedPosition && renderer()->conta inerForFixedPosition() == renderer()->view();
301 }
302
303 bool RenderLayer::scrollsWithRespectTo(const RenderLayer* other) const
304 {
305 if (scrollsWithViewport() != other->scrollsWithViewport())
306 return true;
307 return ancestorScrollingLayer() != other->ancestorScrollingLayer();
308 }
309
310 void RenderLayer::updateLayerPositionsAfterOverflowScroll()
311 {
312 m_clipper.clearClipRectsIncludingDescendants();
313 updateLayerPositionsAfterScrollRecursive();
314 }
315
316 void RenderLayer::updateLayerPositionsAfterScrollRecursive()
317 {
318 if (updateLayerPosition())
319 m_renderer->setPreviousPaintInvalidationRect(m_renderer->boundsRectForPa intInvalidation(m_renderer->containerForPaintInvalidation()));
320
321 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
322 child->updateLayerPositionsAfterScrollRecursive();
323 }
324
325 void RenderLayer::updateTransformationMatrix()
326 {
327 if (m_transform) {
328 RenderBox* box = renderBox();
329 ASSERT(box);
330 m_transform->makeIdentity();
331 box->style()->applyTransform(*m_transform, LayoutSize(box->pixelSnappedS ize()), RenderStyle::IncludeTransformOrigin);
332 makeMatrixRenderable(*m_transform, compositor()->hasAcceleratedCompositi ng());
333 }
334 }
335
336 void RenderLayer::updateTransform(const RenderStyle* oldStyle, RenderStyle* newS tyle)
337 {
338 if (oldStyle && newStyle->transformDataEquivalent(*oldStyle))
339 return;
340
341 // hasTransform() on the renderer is also true when there is transform-style : preserve-3d or perspective set,
342 // so check style too.
343 bool hasTransform = renderer()->hasTransformRelatedProperty() && newStyle->h asTransform();
344 bool had3DTransform = has3DTransform();
345
346 bool hadTransform = m_transform;
347 if (hasTransform != hadTransform) {
348 if (hasTransform)
349 m_transform = adoptPtr(new TransformationMatrix);
350 else
351 m_transform.clear();
352
353 // Layers with transforms act as clip rects roots, so clear the cached c lip rects here.
354 m_clipper.clearClipRectsIncludingDescendants();
355 } else if (hasTransform) {
356 m_clipper.clearClipRectsIncludingDescendants(AbsoluteClipRects);
357 }
358
359 updateTransformationMatrix();
360
361 if (had3DTransform != has3DTransform())
362 dirty3DTransformedDescendantStatus();
363 }
364
365 static RenderLayer* enclosingLayerForContainingBlock(RenderLayer* layer)
366 {
367 if (RenderObject* containingBlock = layer->renderer()->containingBlock())
368 return containingBlock->enclosingLayer();
369 return 0;
370 }
371
372 RenderLayer* RenderLayer::renderingContextRoot()
373 {
374 RenderLayer* renderingContext = 0;
375
376 if (shouldPreserve3D())
377 renderingContext = this;
378
379 for (RenderLayer* current = enclosingLayerForContainingBlock(this); current && current->shouldPreserve3D(); current = enclosingLayerForContainingBlock(curre nt))
380 renderingContext = current;
381
382 return renderingContext;
383 }
384
385 TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOr igin applyOrigin) const
386 {
387 if (!m_transform)
388 return TransformationMatrix();
389
390 // m_transform includes transform-origin, so we need to recompute the transf orm here.
391 if (applyOrigin == RenderStyle::ExcludeTransformOrigin) {
392 RenderBox* box = renderBox();
393 TransformationMatrix currTransform;
394 box->style()->applyTransform(currTransform, LayoutSize(box->pixelSnapped Size()), RenderStyle::ExcludeTransformOrigin);
395 makeMatrixRenderable(currTransform, compositor()->hasAcceleratedComposit ing());
396 return currTransform;
397 }
398
399 return *m_transform;
400 }
401
402 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavio r) const
403 {
404 if (!m_transform)
405 return TransformationMatrix();
406
407 if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
408 TransformationMatrix matrix = *m_transform;
409 makeMatrixRenderable(matrix, false /* flatten 3d */);
410 return matrix;
411 }
412
413 return *m_transform;
414 }
415
416 static bool checkContainingBlockChainForPagination(RenderLayerModelObject* rende rer, RenderBox* ancestorColumnsRenderer)
417 {
418 RenderView* view = renderer->view();
419 RenderLayerModelObject* prevBlock = renderer;
420 RenderBlock* containingBlock;
421 for (containingBlock = renderer->containingBlock();
422 containingBlock && containingBlock != view && containingBlock != ancest orColumnsRenderer;
423 containingBlock = containingBlock->containingBlock())
424 prevBlock = containingBlock;
425
426 // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
427 if (containingBlock != ancestorColumnsRenderer)
428 return false;
429
430 // If the previous block is absolutely positioned, then we can't be paginate d by the columns block.
431 if (prevBlock->isOutOfFlowPositioned())
432 return false;
433
434 // Otherwise we are paginated by the columns block.
435 return true;
436 }
437
438 // Convert a bounding box from flow thread coordinates, relative to |layer|, to visual coordinates, relative to |ancestorLayer|.
439 // See http://www.chromium.org/developers/design-documents/multi-column-layout f or more info on these coordinate types.
440 static void convertFromFlowThreadToVisualBoundingBoxInAncestor(const RenderLayer * layer, const RenderLayer* ancestorLayer, LayoutRect& rect)
441 {
442 RenderLayer* paginationLayer = layer->enclosingPaginationLayer();
443 ASSERT(paginationLayer);
444 RenderFlowThread* flowThread = toRenderFlowThread(paginationLayer->renderer( ));
445
446 // First make the flow thread rectangle relative to the flow thread, not to |layer|.
447 LayoutPoint offsetWithinPaginationLayer;
448 layer->convertToLayerCoords(paginationLayer, offsetWithinPaginationLayer);
449 rect.moveBy(offsetWithinPaginationLayer);
450
451 // Then make the rectangle visual, relative to the fragmentation context. Sp lit our box up into
452 // the actual fragment boxes that render in the columns/pages and unite thos e together to get
453 // our true bounding box.
454 rect = flowThread->fragmentsBoundingBox(rect);
455
456 // Finally, make the visual rectangle relative to |ancestorLayer|.
457 if (ancestorLayer->enclosingPaginationLayer() != paginationLayer) {
458 rect.moveBy(paginationLayer->visualOffsetFromAncestor(ancestorLayer));
459 return;
460 }
461 // The ancestor layer is inside the same pagination layer as |layer|, so we need to subtract
462 // the visual distance from the ancestor layer to the pagination layer.
463 rect.moveBy(-ancestorLayer->visualOffsetFromAncestor(paginationLayer));
464 }
465
466 bool RenderLayer::useRegionBasedColumns() const
467 {
468 return renderer()->document().regionBasedColumnsEnabled();
469 }
470
471 void RenderLayer::updatePaginationRecursive(bool needsPaginationUpdate)
472 {
473 m_isPaginated = false;
474 m_enclosingPaginationLayer = 0;
475
476 if (useRegionBasedColumns() && renderer()->isRenderFlowThread())
477 needsPaginationUpdate = true;
478
479 if (needsPaginationUpdate)
480 updatePagination();
481
482 if (renderer()->hasColumns())
483 needsPaginationUpdate = true;
484
485 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
486 child->updatePaginationRecursive(needsPaginationUpdate);
487 }
488
489 void RenderLayer::updatePagination()
490 {
491 bool usesRegionBasedColumns = useRegionBasedColumns();
492 if ((!usesRegionBasedColumns && compositingState() != NotComposited) || !par ent())
493 return; // FIXME: For now the RenderView can't be paginated. Eventually printing will move to a model where it is though.
494
495 // The main difference between the paginated booleans for the old column cod e and the new column code
496 // is that each paginated layer has to paint on its own with the new code. T here is no
497 // recurring into child layers. This means that the m_isPaginated bits for t he new column code can't just be set on
498 // "roots" that get split and paint all their descendants. Instead each laye r has to be checked individually and
499 // genuinely know if it is going to have to split itself up when painting on ly its contents (and not any other descendant
500 // layers). We track an enclosingPaginationLayer instead of using a simple b it, since we want to be able to get back
501 // to that layer easily.
502 if (usesRegionBasedColumns && renderer()->isRenderFlowThread()) {
503 m_enclosingPaginationLayer = this;
504 return;
505 }
506
507 if (m_stackingNode->isNormalFlowOnly()) {
508 if (usesRegionBasedColumns) {
509 // Content inside a transform is not considered to be paginated, sin ce we simply
510 // paint the transform multiple times in each column, so we don't ha ve to use
511 // fragments for the transformed content.
512 m_enclosingPaginationLayer = parent()->enclosingPaginationLayer();
513 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTra nsformRelatedProperty())
514 m_enclosingPaginationLayer = 0;
515 } else {
516 m_isPaginated = parent()->renderer()->hasColumns();
517 }
518 return;
519 }
520
521 // For the new columns code, we want to walk up our containing block chain l ooking for an enclosing layer. Once
522 // we find one, then we just check its pagination status.
523 if (usesRegionBasedColumns) {
524 RenderView* view = renderer()->view();
525 RenderBlock* containingBlock;
526 for (containingBlock = renderer()->containingBlock();
527 containingBlock && containingBlock != view;
528 containingBlock = containingBlock->containingBlock()) {
529 if (containingBlock->hasLayer()) {
530 // Content inside a transform is not considered to be paginated, since we simply
531 // paint the transform multiple times in each column, so we don' t have to use
532 // fragments for the transformed content.
533 m_enclosingPaginationLayer = containingBlock->layer()->enclosing PaginationLayer();
534 if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->ha sTransformRelatedProperty())
535 m_enclosingPaginationLayer = 0;
536 return;
537 }
538 }
539 return;
540 }
541
542 // If we're not normal flow, then we need to look for a multi-column object between us and our stacking container.
543 RenderLayerStackingNode* ancestorStackingContextNode = m_stackingNode->ances torStackingContextNode();
544 for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
545 if (curr->renderer()->hasColumns()) {
546 m_isPaginated = checkContainingBlockChainForPagination(renderer(), c urr->renderBox());
547 return;
548 }
549 if (curr->stackingNode() == ancestorStackingContextNode)
550 return;
551 }
552 }
553
554 void RenderLayer::clearPaginationRecursive()
555 {
556 m_enclosingPaginationLayer = 0;
557 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
558 child->clearPaginationRecursive();
559 }
560
561 LayoutPoint RenderLayer::positionFromPaintInvalidationBacking(const RenderObject * renderObject, const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* paintInvalidationState)
562 {
563 FloatPoint point = renderObject->localToContainerPoint(FloatPoint(), paintIn validationContainer, 0, 0, paintInvalidationState);
564
565 // FIXME: Eventually we are going to unify coordinates in GraphicsLayer spac e.
566 if (paintInvalidationContainer && paintInvalidationContainer->layer()->group edMapping())
567 mapPointToPaintBackingCoordinates(paintInvalidationContainer, point);
568
569 return LayoutPoint(point);
570 }
571
572 void RenderLayer::mapPointToPaintBackingCoordinates(const RenderLayerModelObject * paintInvalidationContainer, FloatPoint& point)
573 {
574 RenderLayer* paintInvalidationLayer = paintInvalidationContainer->layer();
575 if (!paintInvalidationLayer->groupedMapping()) {
576 point.move(paintInvalidationLayer->compositedLayerMapping()->contentOffs etInCompositingLayer());
577 return;
578 }
579
580 RenderLayerModelObject* transformedAncestor = paintInvalidationLayer->enclos ingTransformedAncestor()->renderer();
581 if (!transformedAncestor)
582 return;
583
584 // |paintInvalidationContainer| may have a local 2D transform on it, so take that into account when mapping into the space of the
585 // transformed ancestor.
586 point = paintInvalidationContainer->localToContainerPoint(point, transformed Ancestor);
587
588 point.moveBy(-paintInvalidationLayer->groupedMapping()->squashingOffsetFromT ransformedAncestor());
589 }
590
591 void RenderLayer::mapRectToPaintBackingCoordinates(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect)
592 {
593 RenderLayer* paintInvalidationLayer = paintInvalidationContainer->layer();
594 if (!paintInvalidationLayer->groupedMapping()) {
595 rect.move(paintInvalidationLayer->compositedLayerMapping()->contentOffse tInCompositingLayer());
596 return;
597 }
598
599 RenderLayerModelObject* transformedAncestor = paintInvalidationLayer->enclos ingTransformedAncestor()->renderer();
600 if (!transformedAncestor)
601 return;
602
603 // |paintInvalidationContainer| may have a local 2D transform on it, so take that into account when mapping into the space of the
604 // transformed ancestor.
605 rect = LayoutRect(paintInvalidationContainer->localToContainerQuad(FloatRect (rect), transformedAncestor).boundingBox());
606
607 rect.moveBy(-paintInvalidationLayer->groupedMapping()->squashingOffsetFromTr ansformedAncestor());
608 }
609
610 void RenderLayer::mapRectToPaintInvalidationBacking(const RenderObject* renderOb ject, const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect , const PaintInvalidationState* paintInvalidationState)
611 {
612 if (!paintInvalidationContainer->layer()->groupedMapping()) {
613 renderObject->mapRectToPaintInvalidationBacking(paintInvalidationContain er, rect, paintInvalidationState);
614 return;
615 }
616
617 // This code adjusts the paint invalidation rectangle to be in the space of the transformed ancestor of the grouped (i.e. squashed)
618 // layer. This is because all layers that squash together need to issue pain t invalidations w.r.t. a single container that is
619 // an ancestor of all of them, in order to properly take into account any lo cal transforms etc.
620 // FIXME: remove this special-case code that works around the paint invalida tion code structure.
621 renderObject->mapRectToPaintInvalidationBacking(paintInvalidationContainer, rect, paintInvalidationState);
622
623 mapRectToPaintBackingCoordinates(paintInvalidationContainer, rect);
624 }
625
626 LayoutRect RenderLayer::computePaintInvalidationRect(const RenderObject* renderO bject, const RenderLayer* paintInvalidationContainer, const PaintInvalidationSta te* paintInvalidationState)
627 {
628 if (!paintInvalidationContainer->groupedMapping())
629 return renderObject->computePaintInvalidationRect(paintInvalidationConta iner->renderer(), paintInvalidationState);
630
631 LayoutRect rect = renderObject->clippedOverflowRectForPaintInvalidation(pain tInvalidationContainer->renderer(), paintInvalidationState);
632 mapRectToPaintBackingCoordinates(paintInvalidationContainer->renderer(), rec t);
633 return rect;
634 }
635
636 void RenderLayer::dirtyVisibleContentStatus()
637 {
638 m_visibleContentStatusDirty = true;
639 if (parent())
640 parent()->dirtyAncestorChainVisibleDescendantStatus();
641 }
642
643 void RenderLayer::potentiallyDirtyVisibleContentStatus(EVisibility visibility)
644 {
645 if (m_visibleContentStatusDirty)
646 return;
647 if (hasVisibleContent() == (visibility == VISIBLE))
648 return;
649 dirtyVisibleContentStatus();
650 }
651
652 void RenderLayer::dirtyAncestorChainVisibleDescendantStatus()
653 {
654 for (RenderLayer* layer = this; layer; layer = layer->parent()) {
655 if (layer->m_visibleDescendantStatusDirty)
656 break;
657
658 layer->m_visibleDescendantStatusDirty = true;
659 }
660 }
661
662 // FIXME: this is quite brute-force. We could be more efficient if we were to
663 // track state and update it as appropriate as changes are made in the Render tr ee.
664 void RenderLayer::updateScrollingStateAfterCompositingChange()
665 {
666 TRACE_EVENT0("blink", "RenderLayer::updateScrollingStateAfterCompositingChan ge");
667 m_hasVisibleNonLayerContent = false;
668 for (RenderObject* r = renderer()->slowFirstChild(); r; r = r->nextSibling() ) {
669 if (!r->hasLayer()) {
670 m_hasVisibleNonLayerContent = true;
671 break;
672 }
673 }
674
675 m_hasNonCompositedChild = false;
676 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
677 if (child->compositingState() == NotComposited) {
678 m_hasNonCompositedChild = true;
679 return;
680 }
681 }
682 }
683
684 // The descendant-dependent flags system is badly broken because we clean dirty
685 // bits in upward tree walks, which means we need to call updateDescendantDepend entFlags
686 // at every node in the tree to fully clean all the dirty bits. While we'll in
687 // the process of fixing this issue, updateDescendantDependentFlagsForEntireSubt ree
688 // provides a big hammer for actually cleaning all the dirty bits in a subtree.
689 //
690 // FIXME: Remove this function once the descendant-dependent flags system keeps
691 // its dirty bits scoped to subtrees.
692 void RenderLayer::updateDescendantDependentFlagsForEntireSubtree()
693 {
694 updateDescendantDependentFlags();
695
696 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
697 child->updateDescendantDependentFlagsForEntireSubtree();
698 }
699
700 void RenderLayer::updateDescendantDependentFlags()
701 {
702 if (m_visibleDescendantStatusDirty) {
703 m_hasVisibleDescendant = false;
704
705 for (RenderLayer* child = firstChild(); child; child = child->nextSiblin g()) {
706 child->updateDescendantDependentFlags();
707
708 if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
709 m_hasVisibleDescendant = true;
710 break;
711 }
712 }
713
714 m_visibleDescendantStatusDirty = false;
715 }
716
717 if (m_visibleContentStatusDirty) {
718 bool previouslyHasVisibleContent = m_hasVisibleContent;
719 if (renderer()->style()->visibility() == VISIBLE)
720 m_hasVisibleContent = true;
721 else {
722 // layer may be hidden but still have some visible content, check fo r this
723 m_hasVisibleContent = false;
724 RenderObject* r = renderer()->slowFirstChild();
725 while (r) {
726 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
727 m_hasVisibleContent = true;
728 break;
729 }
730 RenderObject* rendererFirstChild = r->slowFirstChild();
731 if (rendererFirstChild && !r->hasLayer())
732 r = rendererFirstChild;
733 else if (r->nextSibling())
734 r = r->nextSibling();
735 else {
736 do {
737 r = r->parent();
738 if (r == renderer())
739 r = 0;
740 } while (r && !r->nextSibling());
741 if (r)
742 r = r->nextSibling();
743 }
744 }
745 }
746 m_visibleContentStatusDirty = false;
747
748 if (hasVisibleContent() != previouslyHasVisibleContent) {
749 setNeedsCompositingInputsUpdate();
750 // We need to tell m_renderer to recheck its rect because we
751 // pretend that invisible RenderObjects have 0x0 rects. Changing
752 // visibility therefore changes our rect and we need to visit
753 // this RenderObject during the invalidateTreeIfNeeded walk.
754 m_renderer->setMayNeedPaintInvalidation();
755 }
756 }
757 }
758
759 void RenderLayer::dirty3DTransformedDescendantStatus()
760 {
761 RenderLayerStackingNode* stackingNode = m_stackingNode->ancestorStackingCont extNode();
762 if (!stackingNode)
763 return;
764
765 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
766
767 // This propagates up through preserve-3d hierarchies to the enclosing flatt ening layer.
768 // Note that preserves3D() creates stacking context, so we can just run up t he stacking containers.
769 while (stackingNode && stackingNode->layer()->preserves3D()) {
770 stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
771 stackingNode = stackingNode->ancestorStackingContextNode();
772 }
773 }
774
775 // Return true if this layer or any preserve-3d descendants have 3d.
776 bool RenderLayer::update3DTransformedDescendantStatus()
777 {
778 if (m_3DTransformedDescendantStatusDirty) {
779 m_has3DTransformedDescendant = false;
780
781 m_stackingNode->updateZOrderLists();
782
783 // Transformed or preserve-3d descendants can only be in the z-order lis ts, not
784 // in the normal flow list, so we only need to check those.
785 RenderLayerStackingNodeIterator iterator(*m_stackingNode.get(), Positive ZOrderChildren | NegativeZOrderChildren);
786 while (RenderLayerStackingNode* node = iterator.next())
787 m_has3DTransformedDescendant |= node->layer()->update3DTransformedDe scendantStatus();
788
789 m_3DTransformedDescendantStatusDirty = false;
790 }
791
792 // If we live in a 3d hierarchy, then the layer at the root of that hierarch y needs
793 // the m_has3DTransformedDescendant set.
794 if (preserves3D())
795 return has3DTransform() || m_has3DTransformedDescendant;
796
797 return has3DTransform();
798 }
799
800 bool RenderLayer::updateLayerPosition()
801 {
802 LayoutPoint localPoint;
803 LayoutPoint inlineBoundingBoxOffset; // We don't put this into the RenderLay er x/y for inlines, so we need to subtract it out when done.
804
805 if (renderer()->isInline() && renderer()->isRenderInline()) {
806 RenderInline* inlineFlow = toRenderInline(renderer());
807 IntRect lineBox = inlineFlow->linesBoundingBox();
808 m_size = lineBox.size();
809 inlineBoundingBoxOffset = lineBox.location();
810 localPoint.moveBy(inlineBoundingBoxOffset);
811 } else if (RenderBox* box = renderBox()) {
812 m_size = pixelSnappedIntSize(box->size(), box->location());
813 localPoint.moveBy(box->topLeftLocation());
814 }
815
816 if (!renderer()->isOutOfFlowPositioned() && !renderer()->isColumnSpanAll() & & renderer()->parent()) {
817 // We must adjust our position by walking up the render tree looking for the
818 // nearest enclosing object with a layer.
819 RenderObject* curr = renderer()->parent();
820 while (curr && !curr->hasLayer()) {
821 if (curr->isBox() && !curr->isTableRow()) {
822 // Rows and cells share the same coordinate space (that of the s ection).
823 // Omit them when computing our xpos/ypos.
824 localPoint.moveBy(toRenderBox(curr)->topLeftLocation());
825 }
826 curr = curr->parent();
827 }
828 if (curr->isBox() && curr->isTableRow()) {
829 // Put ourselves into the row coordinate space.
830 localPoint.moveBy(-toRenderBox(curr)->topLeftLocation());
831 }
832 }
833
834 // Subtract our parent's scroll offset.
835 if (renderer()->isOutOfFlowPositioned() && enclosingPositionedAncestor()) {
836 RenderLayer* positionedParent = enclosingPositionedAncestor();
837
838 // For positioned layers, we subtract out the enclosing positioned layer 's scroll offset.
839 if (positionedParent->renderer()->hasOverflowClip()) {
840 IntSize offset = positionedParent->renderBox()->scrolledContentOffse t();
841 localPoint -= offset;
842 }
843
844 if (positionedParent->renderer()->isRelPositioned() && positionedParent- >renderer()->isRenderInline()) {
845 LayoutSize offset = toRenderInline(positionedParent->renderer())->of fsetForInFlowPositionedInline(*toRenderBox(renderer()));
846 localPoint += offset;
847 }
848 } else if (parent()) {
849 // FIXME: This code is very wrong, but luckily only needed in the old/cu rrent multicol
850 // implementation. The compositing system doesn't understand columns and we're hacking
851 // around that fact by faking the position of the RenderLayers when we t hink we'll end up
852 // being composited.
853 if (hasStyleDeterminedDirectCompositingReasons() && !useRegionBasedColum ns()) {
854 // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
855 // They won't split across columns properly.
856 if (!parent()->renderer()->hasColumns() && parent()->renderer()->isD ocumentElement() && renderer()->view()->hasColumns())
857 localPoint += renderer()->view()->columnOffset(localPoint);
858 else
859 localPoint += parent()->renderer()->columnOffset(localPoint);
860 }
861
862 if (parent()->renderer()->hasOverflowClip()) {
863 IntSize scrollOffset = parent()->renderBox()->scrolledContentOffset( );
864 localPoint -= scrollOffset;
865 }
866 }
867
868 bool positionOrOffsetChanged = false;
869 if (renderer()->isRelPositioned()) {
870 LayoutSize newOffset = toRenderBoxModelObject(renderer())->offsetForInFl owPosition();
871 positionOrOffsetChanged = newOffset != m_offsetForInFlowPosition;
872 m_offsetForInFlowPosition = newOffset;
873 localPoint.move(m_offsetForInFlowPosition);
874 } else {
875 m_offsetForInFlowPosition = LayoutSize();
876 }
877
878 // FIXME: We'd really like to just get rid of the concept of a layer rectang le and rely on the renderers.
879 localPoint.moveBy(-inlineBoundingBoxOffset);
880
881 if (m_location != localPoint)
882 positionOrOffsetChanged = true;
883 m_location = localPoint;
884
885 #if ENABLE(ASSERT)
886 m_needsPositionUpdate = false;
887 #endif
888 return positionOrOffsetChanged;
889 }
890
891 TransformationMatrix RenderLayer::perspectiveTransform() const
892 {
893 if (!renderer()->hasTransformRelatedProperty())
894 return TransformationMatrix();
895
896 RenderStyle* style = renderer()->style();
897 if (!style->hasPerspective())
898 return TransformationMatrix();
899
900 // Maybe fetch the perspective from the backing?
901 const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect ();
902 const float boxWidth = borderBox.width();
903 const float boxHeight = borderBox.height();
904
905 float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth);
906 float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight);
907
908 // A perspective origin of 0,0 makes the vanishing point in the center of th e element.
909 // We want it to be in the top-left, so subtract half the height and width.
910 perspectiveOriginX -= boxWidth / 2.0f;
911 perspectiveOriginY -= boxHeight / 2.0f;
912
913 TransformationMatrix t;
914 t.translate(perspectiveOriginX, perspectiveOriginY);
915 t.applyPerspective(style->perspective());
916 t.translate(-perspectiveOriginX, -perspectiveOriginY);
917
918 return t;
919 }
920
921 FloatPoint RenderLayer::perspectiveOrigin() const
922 {
923 if (!renderer()->hasTransformRelatedProperty())
924 return FloatPoint();
925
926 const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
927 RenderStyle* style = renderer()->style();
928
929 return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox .width().toFloat()), floatValueForLength(style->perspectiveOriginY(), borderBox. height().toFloat()));
930 }
931
932 static inline bool isFixedPositionedContainer(RenderLayer* layer)
933 {
934 return layer->isRootLayer() || layer->hasTransformRelatedProperty();
935 }
936
937 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
938 {
939 RenderLayer* curr = parent();
940 while (curr && !curr->isPositionedContainer())
941 curr = curr->parent();
942
943 return curr;
944 }
945
946 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
947 {
948 RenderLayer* curr = parent();
949 while (curr && !curr->isRootLayer() && !curr->renderer()->hasTransformRelate dProperty())
950 curr = curr->parent();
951
952 return curr;
953 }
954
955 LayoutPoint RenderLayer::computeOffsetFromTransformedAncestor() const
956 {
957 const AncestorDependentCompositingInputs& properties = ancestorDependentComp ositingInputs();
958
959 TransformState transformState(TransformState::ApplyTransformDirection, Float Point());
960 // FIXME: add a test that checks flipped writing mode and ApplyContainerFlip are correct.
961 renderer()->mapLocalToContainer(properties.transformAncestor ? properties.tr ansformAncestor->renderer() : 0, transformState, ApplyContainerFlip);
962 transformState.flatten();
963 return LayoutPoint(transformState.lastPlanarPoint());
964 }
965
966 const RenderLayer* RenderLayer::compositingContainer() const
967 {
968 if (stackingNode()->isNormalFlowOnly())
969 return parent();
970 if (RenderLayerStackingNode* ancestorStackingNode = stackingNode()->ancestor StackingContextNode())
971 return ancestorStackingNode->layer();
972 return 0;
973 }
974
975 bool RenderLayer::isPaintInvalidationContainer() const
976 {
977 return compositingState() == PaintsIntoOwnBacking || compositingState() == P aintsIntoGroupedBacking;
978 }
979
980 // Note: enclosingCompositingLayer does not include squashed layers. Compositing stacking children of squashed layers
981 // receive graphics layers that are parented to the compositing ancestor of the squashed layer.
982 RenderLayer* RenderLayer::enclosingLayerWithCompositedLayerMapping(IncludeSelfOr Not includeSelf) const
983 {
984 ASSERT(isAllowedToQueryCompositingState());
985
986 if ((includeSelf == IncludeSelf) && compositingState() != NotComposited && c ompositingState() != PaintsIntoGroupedBacking)
987 return const_cast<RenderLayer*>(this);
988
989 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->co mpositingContainer()) {
990 if (curr->compositingState() != NotComposited && curr->compositingState( ) != PaintsIntoGroupedBacking)
991 return const_cast<RenderLayer*>(curr);
992 }
993
994 return 0;
995 }
996
997 // Return the enclosingCompositedLayerForPaintInvalidation for the given RenderL ayer
998 // including crossing frame boundaries.
999 RenderLayer* RenderLayer::enclosingLayerForPaintInvalidationCrossingFrameBoundar ies() const
1000 {
1001 const RenderLayer* layer = this;
1002 RenderLayer* compositedLayer = 0;
1003 while (!compositedLayer) {
1004 compositedLayer = layer->enclosingLayerForPaintInvalidation();
1005 if (!compositedLayer) {
1006 RenderObject* owner = layer->renderer()->frame()->ownerRenderer();
1007 if (!owner)
1008 break;
1009 layer = owner->enclosingLayer();
1010 }
1011 }
1012 return compositedLayer;
1013 }
1014
1015 RenderLayer* RenderLayer::enclosingLayerForPaintInvalidation() const
1016 {
1017 ASSERT(isAllowedToQueryCompositingState());
1018
1019 if (isPaintInvalidationContainer())
1020 return const_cast<RenderLayer*>(this);
1021
1022 for (const RenderLayer* curr = compositingContainer(); curr; curr = curr->co mpositingContainer()) {
1023 if (curr->isPaintInvalidationContainer())
1024 return const_cast<RenderLayer*>(curr);
1025 }
1026
1027 return 0;
1028 }
1029
1030 void RenderLayer::setNeedsCompositingInputsUpdate()
1031 {
1032 m_needsAncestorDependentCompositingInputsUpdate = true;
1033 m_needsDescendantDependentCompositingInputsUpdate = true;
1034
1035 for (RenderLayer* current = this; current && !current->m_childNeedsCompositi ngInputsUpdate; current = current->parent())
1036 current->m_childNeedsCompositingInputsUpdate = true;
1037
1038 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterCompositingInp utChange);
1039 }
1040
1041 void RenderLayer::updateAncestorDependentCompositingInputs(const AncestorDepende ntCompositingInputs& compositingInputs)
1042 {
1043 m_ancestorDependentCompositingInputs = compositingInputs;
1044 m_needsAncestorDependentCompositingInputsUpdate = false;
1045 }
1046
1047 void RenderLayer::updateDescendantDependentCompositingInputs(const DescendantDep endentCompositingInputs& compositingInputs)
1048 {
1049 m_descendantDependentCompositingInputs = compositingInputs;
1050 m_needsDescendantDependentCompositingInputsUpdate = false;
1051 }
1052
1053 void RenderLayer::didUpdateCompositingInputs()
1054 {
1055 ASSERT(!needsCompositingInputsUpdate());
1056 m_childNeedsCompositingInputsUpdate = false;
1057 if (m_scrollableArea)
1058 m_scrollableArea->updateNeedsCompositedScrolling();
1059 }
1060
1061 bool RenderLayer::hasNonIsolatedDescendantWithBlendMode() const
1062 {
1063 if (descendantDependentCompositingInputs().hasNonIsolatedDescendantWithBlend Mode)
1064 return true;
1065 if (renderer()->isSVGRoot())
1066 return toRenderSVGRoot(renderer())->hasNonIsolatedBlendingDescendants();
1067 return false;
1068 }
1069
1070 void RenderLayer::setCompositingReasons(CompositingReasons reasons, CompositingR easons mask)
1071 {
1072 if ((compositingReasons() & mask) == (reasons & mask))
1073 return;
1074 m_compositingReasons = (reasons & mask) | (compositingReasons() & ~mask);
1075 }
1076
1077 void RenderLayer::setHasCompositingDescendant(bool hasCompositingDescendant)
1078 {
1079 if (m_hasCompositingDescendant == static_cast<unsigned>(hasCompositingDescen dant))
1080 return;
1081
1082 m_hasCompositingDescendant = hasCompositingDescendant;
1083
1084 if (hasCompositedLayerMapping())
1085 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdat eLocal);
1086 }
1087
1088 void RenderLayer::setShouldIsolateCompositedDescendants(bool shouldIsolateCompos itedDescendants)
1089 {
1090 if (m_shouldIsolateCompositedDescendants == static_cast<unsigned>(shouldIsol ateCompositedDescendants))
1091 return;
1092
1093 m_shouldIsolateCompositedDescendants = shouldIsolateCompositedDescendants;
1094
1095 if (hasCompositedLayerMapping())
1096 compositedLayerMapping()->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdat eLocal);
1097 }
1098
1099 bool RenderLayer::hasAncestorWithFilterOutsets() const
1100 {
1101 for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
1102 RenderLayerModelObject* renderer = curr->renderer();
1103 if (renderer->style()->hasFilterOutsets())
1104 return true;
1105 }
1106 return false;
1107 }
1108
1109 static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons t RenderLayer* layer, const RenderLayer* rootLayer,
1110 RenderLayer::TransparencyClipBoxBehavior transparencyBehavior, const LayoutS ize& subPixelAccumulation, PaintBehavior paintBehavior)
1111 {
1112 // If we have a mask, then the clip is limited to the border box area (and t here is
1113 // no need to examine child layers).
1114 if (!layer->renderer()->hasMask()) {
1115 // Note: we don't have to walk z-order lists since transparent elements always establish
1116 // a stacking container. This means we can just walk the layer tree dire ctly.
1117 for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSib ling()) {
1118 if (!layer->reflectionInfo() || layer->reflectionInfo()->reflectionL ayer() != curr)
1119 clipRect.unite(RenderLayer::transparencyClipBox(curr, rootLayer, transparencyBehavior, RenderLayer::DescendantsOfTransparencyClipBox, subPixelAc cumulation, paintBehavior));
1120 }
1121 }
1122
1123 // If we have a reflection, then we need to account for that when we push th e clip. Reflect our entire
1124 // current transparencyClipBox to catch all child layers.
1125 // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
1126 // size into the parent layer.
1127 if (layer->renderer()->hasReflection()) {
1128 LayoutPoint delta;
1129 layer->convertToLayerCoords(rootLayer, delta);
1130 clipRect.move(-delta.x(), -delta.y());
1131 clipRect.unite(layer->renderBox()->reflectedRect(clipRect));
1132 clipRect.moveBy(delta);
1133 }
1134 }
1135
1136 LayoutRect RenderLayer::transparencyClipBox(const RenderLayer* layer, const Rend erLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
1137 TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumula tion, PaintBehavior paintBehavior)
1138 {
1139 // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
1140 // paintDirtyRect, and that should cut down on the amount we have to paint. Still it
1141 // would be better to respect clips.
1142
1143 if (rootLayer != layer && ((transparencyBehavior == PaintingTransparencyClip Box && layer->paintsWithTransform(paintBehavior))
1144 || (transparencyBehavior == HitTestingTransparencyClipBox && layer->hasT ransformRelatedProperty()))) {
1145 // The best we can do here is to use enclosed bounding boxes to establis h a "fuzzy" enough clip to encompass
1146 // the transformed layer and all of its children.
1147 const RenderLayer* paginationLayer = transparencyMode == DescendantsOfTr ansparencyClipBox ? layer->enclosingPaginationLayer() : 0;
1148 const RenderLayer* rootLayerForTransform = paginationLayer ? paginationL ayer : rootLayer;
1149 LayoutPoint delta;
1150 layer->convertToLayerCoords(rootLayerForTransform, delta);
1151
1152 delta.move(subPixelAccumulation);
1153 IntPoint pixelSnappedDelta = roundedIntPoint(delta);
1154 TransformationMatrix transform;
1155 transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y());
1156 transform = transform * *layer->transform();
1157
1158 // We don't use fragment boxes when collecting a transformed layer's bou nding box, since it always
1159 // paints unfragmented.
1160 LayoutRect clipRect = layer->physicalBoundingBox(layer);
1161 expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transp arencyBehavior, subPixelAccumulation, paintBehavior);
1162 clipRect.expand(layer->renderer()->style()->filterOutsets());
1163 LayoutRect result = transform.mapRect(clipRect);
1164 if (!paginationLayer)
1165 return result;
1166
1167 // We have to break up the transformed extent across our columns.
1168 // Split our box up into the actual fragment boxes that render in the co lumns/pages and unite those together to
1169 // get our true bounding box.
1170 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(paginationLay er->renderer());
1171 result = enclosingFlowThread->fragmentsBoundingBox(result);
1172
1173 LayoutPoint rootLayerDelta;
1174 paginationLayer->convertToLayerCoords(rootLayer, rootLayerDelta);
1175 result.moveBy(rootLayerDelta);
1176 return result;
1177 }
1178
1179 LayoutRect clipRect = layer->fragmentsBoundingBox(rootLayer);
1180 expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transp arencyBehavior, subPixelAccumulation, paintBehavior);
1181 clipRect.expand(layer->renderer()->style()->filterOutsets());
1182 clipRect.move(subPixelAccumulation);
1183 return clipRect;
1184 }
1185
1186 LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const Layou tRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, PaintBehavior pai ntBehavior)
1187 {
1188 return intersection(transparencyClipBox(this, rootLayer, PaintingTransparenc yClipBox, RootOfTransparencyClipBox, subPixelAccumulation, paintBehavior), paint DirtyRect);
1189 }
1190
1191 void* RenderLayer::operator new(size_t sz)
1192 {
1193 return partitionAlloc(Partitions::getRenderingPartition(), sz);
1194 }
1195
1196 void RenderLayer::operator delete(void* ptr)
1197 {
1198 partitionFree(ptr);
1199 }
1200
1201 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
1202 {
1203 RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : la stChild();
1204 if (prevSibling) {
1205 child->setPreviousSibling(prevSibling);
1206 prevSibling->setNextSibling(child);
1207 ASSERT(prevSibling != child);
1208 } else
1209 setFirstChild(child);
1210
1211 if (beforeChild) {
1212 beforeChild->setPreviousSibling(child);
1213 child->setNextSibling(beforeChild);
1214 ASSERT(beforeChild != child);
1215 } else
1216 setLastChild(child);
1217
1218 child->m_parent = this;
1219
1220 setNeedsCompositingInputsUpdate();
1221
1222 if (child->stackingNode()->isNormalFlowOnly())
1223 m_stackingNode->dirtyNormalFlowList();
1224
1225 if (!child->stackingNode()->isNormalFlowOnly() || child->firstChild()) {
1226 // Dirty the z-order list in which we are contained. The ancestorStackin gContextNode() can be null in the
1227 // case where we're building up generated content layers. This is ok, si nce the lists will start
1228 // off dirty in that case anyway.
1229 child->stackingNode()->dirtyStackingContextZOrderLists();
1230 }
1231
1232 dirtyAncestorChainVisibleDescendantStatus();
1233 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
1234
1235 child->updateDescendantDependentFlags();
1236 }
1237
1238 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
1239 {
1240 if (oldChild->previousSibling())
1241 oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
1242 if (oldChild->nextSibling())
1243 oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling()) ;
1244
1245 if (m_first == oldChild)
1246 m_first = oldChild->nextSibling();
1247 if (m_last == oldChild)
1248 m_last = oldChild->previousSibling();
1249
1250 if (oldChild->stackingNode()->isNormalFlowOnly())
1251 m_stackingNode->dirtyNormalFlowList();
1252 if (!oldChild->stackingNode()->isNormalFlowOnly() || oldChild->firstChild()) {
1253 // Dirty the z-order list in which we are contained. When called via th e
1254 // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
1255 // from the main layer tree, so we need to null-check the
1256 // |stackingContext| value.
1257 oldChild->stackingNode()->dirtyStackingContextZOrderLists();
1258 }
1259
1260 if (renderer()->style()->visibility() != VISIBLE)
1261 dirtyVisibleContentStatus();
1262
1263 oldChild->setPreviousSibling(0);
1264 oldChild->setNextSibling(0);
1265 oldChild->m_parent = 0;
1266
1267 dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
1268
1269 oldChild->updateDescendantDependentFlags();
1270
1271 if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
1272 dirtyAncestorChainVisibleDescendantStatus();
1273
1274 if (oldChild->enclosingPaginationLayer())
1275 oldChild->clearPaginationRecursive();
1276
1277 return oldChild;
1278 }
1279
1280 void RenderLayer::removeOnlyThisLayer()
1281 {
1282 if (!m_parent)
1283 return;
1284
1285 {
1286 DisableCompositingQueryAsserts disabler; // We need the current composit ing status.
1287 if (isPaintInvalidationContainer()) {
1288 // Our children will be reparented and contained by a new paint inva lidation container,
1289 // so need paint invalidation. CompositingUpdate can't see this laye r (which has been
1290 // removed) so won't do this for us.
1291 setShouldDoFullPaintInvalidationIncludingNonCompositingDescendants() ;
1292 }
1293 }
1294
1295 m_clipper.clearClipRectsIncludingDescendants();
1296
1297 RenderLayer* nextSib = nextSibling();
1298
1299 // Remove the child reflection layer before moving other child layers.
1300 // The reflection layer should not be moved to the parent.
1301 if (m_reflectionInfo)
1302 removeChild(m_reflectionInfo->reflectionLayer());
1303
1304 // Now walk our kids and reattach them to our parent.
1305 RenderLayer* current = m_first;
1306 while (current) {
1307 RenderLayer* next = current->nextSibling();
1308 removeChild(current);
1309 m_parent->addChild(current, nextSib);
1310
1311 // FIXME: We should call a specialized version of this function.
1312 current->updateLayerPositionsAfterLayout();
1313 current = next;
1314 }
1315
1316 // Remove us from the parent.
1317 m_parent->removeChild(this);
1318 m_renderer->destroyLayer();
1319 }
1320
1321 void RenderLayer::insertOnlyThisLayer()
1322 {
1323 if (!m_parent && renderer()->parent()) {
1324 // We need to connect ourselves when our renderer() has a parent.
1325 // Find our enclosingLayer and add ourselves.
1326 RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
1327 ASSERT(parentLayer);
1328 RenderLayer* beforeChild = !parentLayer->reflectionInfo() || parentLayer ->reflectionInfo()->reflectionLayer() != this ? renderer()->parent()->findNextLa yer(parentLayer, renderer()) : 0;
1329 parentLayer->addChild(this, beforeChild);
1330 }
1331
1332 // Remove all descendant layers from the hierarchy and add them to the new p osition.
1333 for (RenderObject* curr = renderer()->slowFirstChild(); curr; curr = curr->n extSibling())
1334 curr->moveLayers(m_parent, this);
1335
1336 // Clear out all the clip rects.
1337 m_clipper.clearClipRectsIncludingDescendants();
1338 }
1339
1340 // Returns the layer reached on the walk up towards the ancestor.
1341 static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLay er* layer, const RenderLayer* ancestorLayer, LayoutPoint& location)
1342 {
1343 ASSERT(ancestorLayer != layer);
1344
1345 const RenderLayerModelObject* renderer = layer->renderer();
1346 EPosition position = renderer->style()->position();
1347
1348 // FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread
1349 // may need to be revisited in a future patch.
1350 // If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute,
1351 // since localToAbsolute maps the coordinates from flow thread to regions co ordinates and regions can be
1352 // positioned in a completely different place in the viewport (RenderView).
1353 if (position == FixedPosition && (!ancestorLayer || ancestorLayer == rendere r->view()->layer())) {
1354 // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
1355 // localToAbsolute() on the RenderView.
1356 FloatPoint absPos = renderer->localToAbsolute(FloatPoint(), IsFixed);
1357 location += LayoutSize(absPos.x(), absPos.y());
1358 return ancestorLayer;
1359 }
1360
1361 // For the fixed positioned elements inside a render flow thread, we should also skip the code path below
1362 // Otherwise, for the case of ancestorLayer == rootLayer and fixed positione d element child of a transformed
1363 // element in render flow thread, we will hit the fixed positioned container before hitting the ancestor layer.
1364 if (position == FixedPosition) {
1365 // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
1366 // (e.g. a transformed layer). It's an error to call convertToLayerCoord s() across a layer with a transform,
1367 // so we should always find the ancestor at or before we find the fixed position container.
1368 RenderLayer* fixedPositionContainerLayer = 0;
1369 bool foundAncestor = false;
1370 for (RenderLayer* currLayer = layer->parent(); currLayer; currLayer = cu rrLayer->parent()) {
1371 if (currLayer == ancestorLayer)
1372 foundAncestor = true;
1373
1374 if (isFixedPositionedContainer(currLayer)) {
1375 fixedPositionContainerLayer = currLayer;
1376 ASSERT_UNUSED(foundAncestor, foundAncestor);
1377 break;
1378 }
1379 }
1380
1381 ASSERT(fixedPositionContainerLayer); // We should have hit the RenderVie w's layer at least.
1382
1383 if (fixedPositionContainerLayer != ancestorLayer) {
1384 LayoutPoint fixedContainerCoords;
1385 layer->convertToLayerCoords(fixedPositionContainerLayer, fixedContai nerCoords);
1386
1387 LayoutPoint ancestorCoords;
1388 ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, anc estorCoords);
1389
1390 location += (fixedContainerCoords - ancestorCoords);
1391 } else {
1392 // RenderView has been handled in the first top-level 'if' block abo ve.
1393 ASSERT(ancestorLayer != renderer->view()->layer());
1394 ASSERT(ancestorLayer->hasTransformRelatedProperty());
1395
1396 location += layer->location();
1397
1398 // The spec (http://dev.w3.org/csswg/css-transforms/#transform-rende ring) doesn't say if a
1399 // fixed-position element under a scrollable transformed element sho uld scroll. However,
1400 // other parts of blink scroll the fixed-position element, and the f ollowing keeps the consistency.
1401 if (RenderLayerScrollableArea* scrollableArea = ancestorLayer->scrol lableArea())
1402 location -= LayoutSize(scrollableArea->scrollOffset());
1403 }
1404 return ancestorLayer;
1405 }
1406
1407 RenderLayer* parentLayer;
1408 if (position == AbsolutePosition) {
1409 // Do what enclosingPositionedAncestor() does, but check for ancestorLay er along the way.
1410 parentLayer = layer->parent();
1411 bool foundAncestorFirst = false;
1412 while (parentLayer) {
1413 // RenderFlowThread is a positioned container, child of RenderView, positioned at (0,0).
1414 // This implies that, for out-of-flow positioned elements inside a R enderFlowThread,
1415 // we are bailing out before reaching root layer.
1416 if (parentLayer->isPositionedContainer())
1417 break;
1418
1419 if (parentLayer == ancestorLayer) {
1420 foundAncestorFirst = true;
1421 break;
1422 }
1423
1424 parentLayer = parentLayer->parent();
1425 }
1426
1427 // We should not reach RenderView layer past the RenderFlowThread layer for any
1428 // children of the RenderFlowThread.
1429 ASSERT(!renderer->flowThreadContainingBlock() || parentLayer != renderer ->view()->layer());
1430
1431 if (foundAncestorFirst) {
1432 // Found ancestorLayer before the abs. positioned container, so comp ute offset of both relative
1433 // to enclosingPositionedAncestor and subtract.
1434 RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAn cestor();
1435
1436 LayoutPoint thisCoords;
1437 layer->convertToLayerCoords(positionedAncestor, thisCoords);
1438
1439 LayoutPoint ancestorCoords;
1440 ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoor ds);
1441
1442 location += (thisCoords - ancestorCoords);
1443 return ancestorLayer;
1444 }
1445 } else if (renderer->isColumnSpanAll()) {
1446 RenderBlock* multicolContainer = renderer->containingBlock();
1447 ASSERT(toRenderBlockFlow(multicolContainer)->multiColumnFlowThread());
1448 parentLayer = multicolContainer->layer();
1449 ASSERT(parentLayer);
1450 } else {
1451 parentLayer = layer->parent();
1452 }
1453
1454 if (!parentLayer)
1455 return 0;
1456
1457 location += layer->location();
1458 return parentLayer;
1459 }
1460
1461 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutP oint& location) const
1462 {
1463 if (ancestorLayer == this)
1464 return;
1465
1466 const RenderLayer* currLayer = this;
1467 while (currLayer && currLayer != ancestorLayer)
1468 currLayer = accumulateOffsetTowardsAncestor(currLayer, ancestorLayer, lo cation);
1469 }
1470
1471 void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutR ect& rect) const
1472 {
1473 LayoutPoint delta;
1474 convertToLayerCoords(ancestorLayer, delta);
1475 rect.moveBy(delta);
1476 }
1477
1478 LayoutPoint RenderLayer::visualOffsetFromAncestor(const RenderLayer* ancestorLay er) const
1479 {
1480 LayoutPoint offset;
1481 if (ancestorLayer == this)
1482 return offset;
1483 RenderLayer* paginationLayer = enclosingPaginationLayer();
1484 if (paginationLayer == this)
1485 paginationLayer = parent()->enclosingPaginationLayer();
1486 if (!paginationLayer) {
1487 convertToLayerCoords(ancestorLayer, offset);
1488 return offset;
1489 }
1490
1491 RenderFlowThread* flowThread = toRenderFlowThread(paginationLayer->renderer( ));
1492 convertToLayerCoords(paginationLayer, offset);
1493 offset = flowThread->flowThreadPointToVisualPoint(offset);
1494 if (ancestorLayer == paginationLayer)
1495 return offset;
1496
1497 if (ancestorLayer->enclosingPaginationLayer() != paginationLayer) {
1498 offset.moveBy(paginationLayer->visualOffsetFromAncestor(ancestorLayer));
1499 } else {
1500 // The ancestor layer is also inside the pagination layer, so we need to subtract the visual
1501 // distance from the ancestor layer to the pagination layer.
1502 offset.moveBy(-ancestorLayer->visualOffsetFromAncestor(paginationLayer)) ;
1503 }
1504 return offset;
1505 }
1506
1507 void RenderLayer::didUpdateNeedsCompositedScrolling()
1508 {
1509 updateSelfPaintingLayer();
1510 }
1511
1512 void RenderLayer::updateReflectionInfo(const RenderStyle* oldStyle)
1513 {
1514 ASSERT(!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle) );
1515 if (renderer()->hasReflection()) {
1516 if (!m_reflectionInfo)
1517 m_reflectionInfo = adoptPtr(new RenderLayerReflectionInfo(*renderBox ()));
1518 m_reflectionInfo->updateAfterStyleChange(oldStyle);
1519 } else if (m_reflectionInfo) {
1520 m_reflectionInfo->destroy();
1521 m_reflectionInfo = nullptr;
1522 }
1523 }
1524
1525 void RenderLayer::updateStackingNode()
1526 {
1527 if (requiresStackingNode())
1528 m_stackingNode = adoptPtr(new RenderLayerStackingNode(this));
1529 else
1530 m_stackingNode = nullptr;
1531 }
1532
1533 void RenderLayer::updateScrollableArea()
1534 {
1535 if (requiresScrollableArea())
1536 m_scrollableArea = adoptPtr(new RenderLayerScrollableArea(*this));
1537 else
1538 m_scrollableArea = nullptr;
1539 }
1540
1541 bool RenderLayer::hasOverflowControls() const
1542 {
1543 return m_scrollableArea && (m_scrollableArea->hasScrollbar() || m_scrollable Area->scrollCorner() || renderer()->style()->resize() != RESIZE_NONE);
1544 }
1545
1546 void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, const LayoutRect& dirtyRect,
1547 ClipRectsCacheSlot clipRectsCacheSlot, OverlayScrollbarSizeRelevancy inOverl ayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const L ayoutPoint* offsetFromRoot,
1548 const LayoutSize& subPixelAccumulation, const LayoutRect* layerBoundingBox)
1549 {
1550 if (!enclosingPaginationLayer() || hasTransformRelatedProperty()) {
1551 // For unpaginated layers, there is only one fragment.
1552 LayerFragment fragment;
1553 ClipRectsContext clipRectsContext(rootLayer, clipRectsCacheSlot, inOverl ayScrollbarSizeRelevancy, subPixelAccumulation);
1554 if (respectOverflowClip == IgnoreOverflowClip)
1555 clipRectsContext.setIgnoreOverflowClip();
1556 clipper().calculateRects(clipRectsContext, dirtyRect, fragment.layerBoun ds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offs etFromRoot);
1557 fragments.append(fragment);
1558 return;
1559 }
1560
1561 // Compute our offset within the enclosing pagination layer.
1562 LayoutPoint offsetWithinPaginatedLayer;
1563 convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginatedLayer) ;
1564
1565 // Calculate clip rects relative to the enclosingPaginationLayer. The purpos e of this call is to determine our bounds clipped to intermediate
1566 // 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.
1567 ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), clip RectsCacheSlot, inOverlayScrollbarSizeRelevancy);
1568 if (respectOverflowClip == IgnoreOverflowClip)
1569 paginationClipRectsContext.setIgnoreOverflowClip();
1570 LayoutRect layerBoundsInFlowThread;
1571 ClipRect backgroundRectInFlowThread;
1572 ClipRect foregroundRectInFlowThread;
1573 ClipRect outlineRectInFlowThread;
1574 clipper().calculateRects(paginationClipRectsContext, LayoutRect::infiniteInt Rect(), layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlo wThread,
1575 outlineRectInFlowThread, &offsetWithinPaginatedLayer);
1576
1577 // Take our bounding box within the flow thread and clip it.
1578 LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingB ox : physicalBoundingBox(enclosingPaginationLayer(), &offsetWithinPaginatedLayer );
1579 layerBoundingBoxInFlowThread.intersect(backgroundRectInFlowThread.rect());
1580
1581 // Make the dirty rect relative to the fragmentation context (multicol conta iner, etc.).
1582 RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginati onLayer()->renderer());
1583 LayoutPoint offsetOfPaginationLayerFromRoot; // Visual offset from the root layer to the nearest fragmentation context.
1584 bool rootLayerIsInsidePaginationLayer = rootLayer->enclosingPaginationLayer( ) == enclosingPaginationLayer();
1585 if (rootLayerIsInsidePaginationLayer) {
1586 // The root layer is in the same fragmentation context as this layer, so we need to look
1587 // inside it and subtract the offset between the fragmentation context a nd the root layer.
1588 offsetOfPaginationLayerFromRoot = -rootLayer->visualOffsetFromAncestor(e nclosingPaginationLayer());
1589 } else {
1590 offsetOfPaginationLayerFromRoot = enclosingPaginationLayer()->visualOffs etFromAncestor(rootLayer);
1591 }
1592 LayoutRect dirtyRectInFlowThread(dirtyRect);
1593 dirtyRectInFlowThread.moveBy(-offsetOfPaginationLayerFromRoot);
1594
1595 // Tell the flow thread to collect the fragments. We pass enough information to create a minimal number of fragments based off the pages/columns
1596 // that intersect the actual dirtyRect as well as the pages/columns that int ersect our layer's bounding box.
1597 enclosingFlowThread->collectLayerFragments(fragments, layerBoundingBoxInFlow Thread, dirtyRectInFlowThread);
1598
1599 if (fragments.isEmpty())
1600 return;
1601
1602 // Get the parent clip rects of the pagination layer, since we need to inter sect with that when painting column contents.
1603 ClipRect ancestorClipRect = dirtyRect;
1604 if (const RenderLayer* paginationParentLayer = enclosingPaginationLayer()->p arent()) {
1605 const RenderLayer* ancestorLayer = rootLayerIsInsidePaginationLayer ? pa ginationParentLayer : rootLayer;
1606 ClipRectsContext clipRectsContext(ancestorLayer, clipRectsCacheSlot, inO verlayScrollbarSizeRelevancy);
1607 if (respectOverflowClip == IgnoreOverflowClip)
1608 clipRectsContext.setIgnoreOverflowClip();
1609 ancestorClipRect = enclosingPaginationLayer()->clipper().backgroundClipR ect(clipRectsContext);
1610 if (rootLayerIsInsidePaginationLayer)
1611 ancestorClipRect.moveBy(-rootLayer->visualOffsetFromAncestor(ancesto rLayer));
1612 ancestorClipRect.intersect(dirtyRect);
1613 }
1614
1615 for (size_t i = 0; i < fragments.size(); ++i) {
1616 LayerFragment& fragment = fragments.at(i);
1617
1618 // Set our four rects with all clipping applied that was internal to the flow thread.
1619 fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, f oregroundRectInFlowThread, outlineRectInFlowThread);
1620
1621 // Shift to the root-relative physical position used when painting the f low thread in this fragment.
1622 fragment.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromR oot);
1623
1624 // Intersect the fragment with our ancestor's background clip so that e. g., columns in an overflow:hidden block are
1625 // properly clipped by the overflow.
1626 fragment.intersect(ancestorClipRect.rect());
1627
1628 // Now intersect with our pagination clip. This will typically mean we'r e just intersecting the dirty rect with the column
1629 // clip, so the column clip ends up being all we apply.
1630 fragment.intersect(fragment.paginationClip);
1631 }
1632 }
1633
1634 static inline LayoutRect frameVisibleRect(RenderObject* renderer)
1635 {
1636 FrameView* frameView = renderer->document().view();
1637 if (!frameView)
1638 return LayoutRect();
1639
1640 return frameView->visibleContentRect();
1641 }
1642
1643 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
1644 {
1645 return hitTest(request, result.hitTestLocation(), result);
1646 }
1647
1648 bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation& hitTestLocation, HitTestResult& result)
1649 {
1650 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
1651
1652 // RenderView should make sure to update layout before entering hit testing
1653 ASSERT(!renderer()->frame()->view()->layoutPending());
1654 ASSERT(!renderer()->document().renderView()->needsLayout());
1655
1656 // Start with frameVisibleRect to ensure we include the scrollbars.
1657 LayoutRect hitTestArea = frameVisibleRect(renderer());
1658 if (request.ignoreClipping())
1659 hitTestArea.unite(renderer()->view()->documentRect());
1660
1661 RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestAre a, hitTestLocation, false);
1662 if (!insideLayer) {
1663 // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
1664 // return ourselves. We do this so mouse events continue getting deliver ed after a drag has
1665 // exited the WebView, and so hit testing over a scrollbar hits the cont ent document.
1666 // In addtion, it is possible for the mouse to stay in the document but there is no element.
1667 // At that time, the events of the mouse should be fired.
1668 LayoutPoint hitPoint = hitTestLocation.point();
1669 if (!request.isChildFrameHitTest() && ((request.active() || request.rele ase()) || (request.move() && hitTestArea.contains(hitPoint.x(), hitPoint.y()))) && isRootLayer()) {
1670 renderer()->updateHitTestResult(result, toRenderView(renderer())->fl ipForWritingMode(hitTestLocation.point()));
1671 insideLayer = this;
1672 }
1673 }
1674
1675 // Now determine if the result is inside an anchor - if the urlElement isn't already set.
1676 Node* node = result.innerNode();
1677 if (node && !result.URLElement())
1678 result.setURLElement(node->enclosingLinkEventParentOrSelf());
1679
1680 // Now return whether we were inside this layer (this will always be true fo r the root
1681 // layer).
1682 return insideLayer;
1683 }
1684
1685 Node* RenderLayer::enclosingElement() const
1686 {
1687 for (RenderObject* r = renderer(); r; r = r->parent()) {
1688 if (Node* e = r->node())
1689 return e;
1690 }
1691 ASSERT_NOT_REACHED();
1692 return 0;
1693 }
1694
1695 bool RenderLayer::isInTopLayer() const
1696 {
1697 Node* node = renderer()->node();
1698 return node && node->isElementNode() && toElement(node)->isInTopLayer();
1699 }
1700
1701 // Compute the z-offset of the point in the transformState.
1702 // This is effectively projecting a ray normal to the plane of ancestor, finding where that
1703 // ray intersects target, and computing the z delta between those two points.
1704 static double computeZOffset(const HitTestingTransformState& transformState)
1705 {
1706 // We got an affine transform, so no z-offset
1707 if (transformState.m_accumulatedTransform.isAffine())
1708 return 0;
1709
1710 // Flatten the point into the target plane
1711 FloatPoint targetPoint = transformState.mappedPoint();
1712
1713 // Now map the point back through the transform, which computes Z.
1714 FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoin t(FloatPoint3D(targetPoint));
1715 return backmappedPoint.z();
1716 }
1717
1718 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(Rend erLayer* rootLayer, RenderLayer* containerLayer,
1719 const LayoutRect& hitTestRect, const Hit TestLocation& hitTestLocation,
1720 const HitTestingTransformState* containe rTransformState,
1721 const LayoutPoint& translationOffset) co nst
1722 {
1723 RefPtr<HitTestingTransformState> transformState;
1724 LayoutPoint offset;
1725 if (containerTransformState) {
1726 // If we're already computing transform state, then it's relative to the container (which we know is non-null).
1727 transformState = HitTestingTransformState::create(*containerTransformSta te);
1728 convertToLayerCoords(containerLayer, offset);
1729 } else {
1730 // If this is the first time we need to make transform state, then base it off of hitTestLocation,
1731 // which is relative to rootLayer.
1732 transformState = HitTestingTransformState::create(hitTestLocation.transf ormedPoint(), hitTestLocation.transformedRect(), FloatQuad(hitTestRect));
1733 convertToLayerCoords(rootLayer, offset);
1734 }
1735 offset.moveBy(translationOffset);
1736
1737 RenderObject* containerRenderer = containerLayer ? containerLayer->renderer( ) : 0;
1738 if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
1739 TransformationMatrix containerTransform;
1740 renderer()->getTransformFromContainer(containerRenderer, toLayoutSize(of fset), containerTransform);
1741 transformState->applyTransform(containerTransform, HitTestingTransformSt ate::AccumulateTransform);
1742 } else {
1743 transformState->translate(offset.x(), offset.y(), HitTestingTransformSta te::AccumulateTransform);
1744 }
1745
1746 return transformState;
1747 }
1748
1749
1750 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, doubl e* zOffset, const HitTestingTransformState* transformState)
1751 {
1752 if (!hitLayer)
1753 return false;
1754
1755 // The hit layer is depth-sorting with other layers, so just say that it was hit.
1756 if (canDepthSort)
1757 return true;
1758
1759 // We need to look at z-depth to decide if this layer was hit.
1760 if (zOffset) {
1761 ASSERT(transformState);
1762 // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
1763 double childZOffset = computeZOffset(*transformState);
1764 if (childZOffset > *zOffset) {
1765 *zOffset = childZOffset;
1766 return true;
1767 }
1768 return false;
1769 }
1770
1771 return true;
1772 }
1773
1774 // hitTestLocation and hitTestRect are relative to rootLayer.
1775 // A 'flattening' layer is one preserves3D() == false.
1776 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
1777 // transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the c ontaining flattening layer.
1778 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
1779 //
1780 // If zOffset is non-null (which indicates that the caller wants z offset inform ation),
1781 // *zOffset on return is the z offset of the hit point relative to the containi ng flattening layer.
1782 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* cont ainerLayer, const HitTestRequest& request, HitTestResult& result,
1783 const LayoutRect& hitTestRect, const HitT estLocation& hitTestLocation, bool appliedTransform,
1784 const HitTestingTransformState* transform State, double* zOffset)
1785 {
1786 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
1787 return 0;
1788
1789 // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
1790
1791 // Apply a transform if we have one.
1792 if (transform() && !appliedTransform) {
1793 if (enclosingPaginationLayer())
1794 return hitTestTransformedLayerInFragments(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
1795
1796 // Make sure the parent's clip rects have been calculated.
1797 if (parent()) {
1798 ClipRect clipRect = clipper().backgroundClipRect(ClipRectsContext(ro otLayer, RootRelativeClipRects, IncludeOverlayScrollbarSize));
1799 // Go ahead and test the enclosing clip now.
1800 if (!clipRect.intersects(hitTestLocation))
1801 return 0;
1802 }
1803
1804 return hitTestLayerByApplyingTransform(rootLayer, containerLayer, reques t, result, hitTestRect, hitTestLocation, transformState, zOffset);
1805 }
1806
1807 // Ensure our lists and 3d status are up-to-date.
1808 m_stackingNode->updateLayerListsIfNeeded();
1809 update3DTransformedDescendantStatus();
1810
1811 RefPtr<HitTestingTransformState> localTransformState;
1812 if (appliedTransform) {
1813 // We computed the correct state in the caller (above code), so just ref erence it.
1814 ASSERT(transformState);
1815 localTransformState = const_cast<HitTestingTransformState*>(transformSta te);
1816 } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
1817 // We need transform state for the first time, or to offset the containe r state, so create it here.
1818 localTransformState = createLocalTransformState(rootLayer, containerLaye r, hitTestRect, hitTestLocation, transformState);
1819 }
1820
1821 // Check for hit test on backface if backface-visibility is 'hidden'
1822 if (localTransformState && renderer()->style()->backfaceVisibility() == Back faceVisibilityHidden) {
1823 TransformationMatrix invertedMatrix = localTransformState->m_accumulated Transform.inverse();
1824 // If the z-vector of the matrix is negative, the back is facing towards the viewer.
1825 if (invertedMatrix.m33() < 0)
1826 return 0;
1827 }
1828
1829 RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformS tate;
1830 if (localTransformState && !preserves3D()) {
1831 // Keep a copy of the pre-flattening state, for computing z-offsets for the container
1832 unflattenedTransformState = HitTestingTransformState::create(*localTrans formState);
1833 // This layer is flattening, so flatten the state passed to descendants.
1834 localTransformState->flatten();
1835 }
1836
1837 // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
1838 // descendants.
1839 double localZOffset = -std::numeric_limits<double>::infinity();
1840 double* zOffsetForDescendantsPtr = 0;
1841 double* zOffsetForContentsPtr = 0;
1842
1843 bool depthSortDescendants = false;
1844 if (preserves3D()) {
1845 depthSortDescendants = true;
1846 // Our layers can depth-test with our container, so share the z depth po inter with the container, if it passed one down.
1847 zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
1848 zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
1849 } else if (zOffset) {
1850 zOffsetForDescendantsPtr = 0;
1851 // Container needs us to give back a z offset for the hit layer.
1852 zOffsetForContentsPtr = zOffset;
1853 }
1854
1855 // This variable tracks which layer the mouse ends up being inside.
1856 RenderLayer* candidateLayer = 0;
1857
1858 // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
1859 RenderLayer* hitLayer = hitTestChildren(PositiveZOrderChildren, rootLayer, r equest, result, hitTestRect, hitTestLocation,
1860 localTransformState.get(), zOffsetForDes cendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
1861 if (hitLayer) {
1862 if (!depthSortDescendants)
1863 return hitLayer;
1864 candidateLayer = hitLayer;
1865 }
1866
1867 // Now check our overflow objects.
1868 hitLayer = hitTestChildren(NormalFlowChildren, rootLayer, request, result, h itTestRect, hitTestLocation,
1869 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
1870 if (hitLayer) {
1871 if (!depthSortDescendants)
1872 return hitLayer;
1873 candidateLayer = hitLayer;
1874 }
1875
1876 // Collect the fragments. This will compute the clip rectangles for each lay er fragment.
1877 LayerFragments layerFragments;
1878 collectFragments(layerFragments, rootLayer, hitTestRect, RootRelativeClipRec ts, IncludeOverlayScrollbarSize);
1879
1880 if (m_scrollableArea && m_scrollableArea->hitTestResizerInFragments(layerFra gments, hitTestLocation)) {
1881 renderer()->updateHitTestResult(result, hitTestLocation.point());
1882 return this;
1883 }
1884
1885 // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. Check
1886 // every fragment in reverse order.
1887 if (isSelfPaintingLayer()) {
1888 // Hit test with a temporary HitTestResult, because we only want to comm it to 'result' if we know we're frontmost.
1889 HitTestResult tempResult(result.hitTestLocation());
1890 bool insideFragmentForegroundRect = false;
1891 if (hitTestContentsForFragments(layerFragments, request, tempResult, hit TestLocation, HitTestDescendants, insideFragmentForegroundRect)
1892 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTra nsformState.get())) {
1893 if (result.isRectBasedTest())
1894 result.append(tempResult);
1895 else
1896 result = tempResult;
1897 if (!depthSortDescendants)
1898 return this;
1899 // Foreground can depth-sort with descendant layers, so keep this as a candidate.
1900 candidateLayer = this;
1901 } else if (insideFragmentForegroundRect && result.isRectBasedTest())
1902 result.append(tempResult);
1903 }
1904
1905 // Now check our negative z-index children.
1906 hitLayer = hitTestChildren(NegativeZOrderChildren, rootLayer, request, resul t, hitTestRect, hitTestLocation,
1907 localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattene dTransformState.get(), depthSortDescendants);
1908 if (hitLayer) {
1909 if (!depthSortDescendants)
1910 return hitLayer;
1911 candidateLayer = hitLayer;
1912 }
1913
1914 // If we found a layer, return. Child layers, and foreground always render i n front of background.
1915 if (candidateLayer)
1916 return candidateLayer;
1917
1918 if (isSelfPaintingLayer()) {
1919 HitTestResult tempResult(result.hitTestLocation());
1920 bool insideFragmentBackgroundRect = false;
1921 if (hitTestContentsForFragments(layerFragments, request, tempResult, hit TestLocation, HitTestSelf, insideFragmentBackgroundRect)
1922 && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTra nsformState.get())) {
1923 if (result.isRectBasedTest())
1924 result.append(tempResult);
1925 else
1926 result = tempResult;
1927 return this;
1928 }
1929 if (insideFragmentBackgroundRect && result.isRectBasedTest())
1930 result.append(tempResult);
1931 }
1932
1933 return 0;
1934 }
1935
1936 bool RenderLayer::hitTestContentsForFragments(const LayerFragments& layerFragmen ts, const HitTestRequest& request, HitTestResult& result,
1937 const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter, bool& i nsideClipRect) const
1938 {
1939 if (layerFragments.isEmpty())
1940 return false;
1941
1942 for (int i = layerFragments.size() - 1; i >= 0; --i) {
1943 const LayerFragment& fragment = layerFragments.at(i);
1944 if ((hitTestFilter == HitTestSelf && !fragment.backgroundRect.intersects (hitTestLocation))
1945 || (hitTestFilter == HitTestDescendants && !fragment.foregroundRect. intersects(hitTestLocation)))
1946 continue;
1947 insideClipRect = true;
1948 if (hitTestContents(request, result, fragment.layerBounds, hitTestLocati on, hitTestFilter))
1949 return true;
1950 }
1951
1952 return false;
1953 }
1954
1955 RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLa yer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
1956 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
1957 {
1958 LayerFragments enclosingPaginationFragments;
1959 LayoutPoint offsetOfPaginationLayerFromRoot;
1960 // FIXME: We're missing a sub-pixel offset here crbug.com/348728
1961 LayoutRect transformedExtent = transparencyClipBox(this, enclosingPagination Layer(), HitTestingTransparencyClipBox, RenderLayer::RootOfTransparencyClipBox, LayoutSize());
1962 enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, r ootLayer, hitTestRect,
1963 RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent);
1964
1965 for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) {
1966 const LayerFragment& fragment = enclosingPaginationFragments.at(i);
1967
1968 // Apply the page/column clip for this fragment, as well as any clips es tablished by layers in between us and
1969 // the enclosing pagination layer.
1970 LayoutRect clipRect = fragment.backgroundRect.rect();
1971
1972 // Now compute the clips within a given fragment
1973 if (parent() != enclosingPaginationLayer()) {
1974 enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOf PaginationLayerFromRoot);
1975 LayoutRect parentClipRect = clipper().backgroundClipRect(ClipRectsCo ntext(enclosingPaginationLayer(), RootRelativeClipRects, IncludeOverlayScrollbar Size)).rect();
1976 parentClipRect.moveBy(fragment.paginationOffset + offsetOfPagination LayerFromRoot);
1977 clipRect.intersect(parentClipRect);
1978 }
1979
1980 if (!hitTestLocation.intersects(clipRect))
1981 continue;
1982
1983 RenderLayer* hitLayer = hitTestLayerByApplyingTransform(rootLayer, conta inerLayer, request, result, hitTestRect, hitTestLocation,
1984 transformState, zOffset, fragment.paginationOffset);
1985 if (hitLayer)
1986 return hitLayer;
1987 }
1988
1989 return 0;
1990 }
1991
1992 RenderLayer* RenderLayer::hitTestLayerByApplyingTransform(RenderLayer* rootLayer , RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& res ult,
1993 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
1994 const LayoutPoint& translationOffset)
1995 {
1996 // Create a transform state to accumulate this transform.
1997 RefPtr<HitTestingTransformState> newTransformState = createLocalTransformSta te(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, tran slationOffset);
1998
1999 // If the transform can't be inverted, then don't hit test this layer at all .
2000 if (!newTransformState->m_accumulatedTransform.isInvertible())
2001 return 0;
2002
2003 // Compute the point and the hit test rect in the coords of this layer by us ing the values
2004 // from the transformState, which store the point and quad in the coords of the last flattened
2005 // layer, and the accumulated transform which lets up map through preserve-3 d layers.
2006 //
2007 // We can't just map hitTestLocation and hitTestRect because they may have b een flattened (losing z)
2008 // by our container.
2009 FloatPoint localPoint = newTransformState->mappedPoint();
2010 FloatQuad localPointQuad = newTransformState->mappedQuad();
2011 LayoutRect localHitTestRect = newTransformState->boundsOfMappedArea();
2012 HitTestLocation newHitTestLocation;
2013 if (hitTestLocation.isRectBasedTest())
2014 newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
2015 else
2016 newHitTestLocation = HitTestLocation(localPoint);
2017
2018 // Now do a hit test with the root layer shifted to be us.
2019 return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestLocation, true, newTransformState.get(), zOffset);
2020 }
2021
2022 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestLocation& hitTestLocation, H itTestFilter hitTestFilter) const
2023 {
2024 ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
2025
2026 if (!renderer()->hitTest(request, result, hitTestLocation, toLayoutPoint(lay erBounds.location() - renderBoxLocation()), hitTestFilter)) {
2027 // It's wrong to set innerNode, but then claim that you didn't hit anyth ing, unless it is
2028 // a rect-based test.
2029 ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBa sedTestResult().size()));
2030 return false;
2031 }
2032
2033 // For positioned generated content, we might still not have a
2034 // node by the time we get to the layer level, since none of
2035 // the content in the layer has an element. So just walk up
2036 // the tree.
2037 if (!result.innerNode() || !result.innerNonSharedNode()) {
2038 Node* e = enclosingElement();
2039 if (!result.innerNode())
2040 result.setInnerNode(e);
2041 if (!result.innerNonSharedNode())
2042 result.setInnerNonSharedNode(e);
2043 }
2044
2045 return true;
2046 }
2047
2048 RenderLayer* RenderLayer::hitTestChildren(ChildrenIteration childrentoVisit, Ren derLayer* rootLayer,
2049 const HitTestRequest& request, HitTestResult& result,
2050 const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
2051 const HitTestingTransformState* transformState,
2052 double* zOffsetForDescendants, double* zOffset,
2053 const HitTestingTransformState* unflattenedTransformState,
2054 bool depthSortDescendants)
2055 {
2056 if (!hasSelfPaintingLayerDescendant())
2057 return 0;
2058
2059 RenderLayer* resultLayer = 0;
2060 RenderLayerStackingNodeReverseIterator iterator(*m_stackingNode, childrentoV isit);
2061 while (RenderLayerStackingNode* child = iterator.next()) {
2062 RenderLayer* childLayer = child->layer();
2063 RenderLayer* hitLayer = 0;
2064 HitTestResult tempResult(result.hitTestLocation());
2065 if (childLayer->isPaginated())
2066 hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request , tempResult, hitTestRect, hitTestLocation, transformState, zOffsetForDescendant s);
2067 else
2068 hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempRe sult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants );
2069
2070 // If it a rect-based test, we can safely append the temporary result si nce it might had hit
2071 // nodes but not necesserily had hitLayer set.
2072 if (result.isRectBasedTest())
2073 result.append(tempResult);
2074
2075 if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedT ransformState)) {
2076 resultLayer = hitLayer;
2077 if (!result.isRectBasedTest())
2078 result = tempResult;
2079 if (!depthSortDescendants)
2080 break;
2081 }
2082 }
2083
2084 return resultLayer;
2085 }
2086
2087 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, Re nderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
2088 const LayoutRect& hitTestRe ct, const HitTestLocation& hitTestLocation, const HitTestingTransformState* tran sformState, double* zOffset)
2089 {
2090 Vector<RenderLayer*> columnLayers;
2091 RenderLayerStackingNode* ancestorNode = m_stackingNode->isNormalFlowOnly() ? parent()->stackingNode() : m_stackingNode->ancestorStackingContextNode();
2092 for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
2093 if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagina tion(childLayer->renderer(), curr->renderBox()))
2094 columnLayers.append(curr);
2095 if (curr->stackingNode() == ancestorNode)
2096 break;
2097 }
2098
2099 ASSERT(columnLayers.size());
2100 return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitT estRect, hitTestLocation, transformState, zOffset,
2101 columnLayers, columnLayers.size() - 1);
2102 }
2103
2104 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, Rend erLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
2105 const LayoutRect& hitTestRect , const HitTestLocation& hitTestLocation, const HitTestingTransformState* transf ormState, double* zOffset,
2106 const Vector<RenderLayer*>& c olumnLayers, size_t columnIndex)
2107 {
2108 RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer ());
2109
2110 ASSERT(columnBlock && columnBlock->hasColumns());
2111 if (!columnBlock || !columnBlock->hasColumns())
2112 return 0;
2113
2114 LayoutPoint layerOffset;
2115 columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
2116
2117 ColumnInfo* colInfo = columnBlock->columnInfo();
2118 int colCount = columnBlock->columnCount(colInfo);
2119
2120 // We have to go backwards from the last column to the first.
2121 bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
2122 LayoutUnit logicalLeft = columnBlock->logicalLeftOffsetForContent();
2123 LayoutUnit currLogicalTopOffset = 0;
2124 int i;
2125 for (i = 0; i < colCount; i++) {
2126 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
2127 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.widt h());
2128 if (columnBlock->style()->isFlippedBlocksWritingMode())
2129 currLogicalTopOffset += blockDelta;
2130 else
2131 currLogicalTopOffset -= blockDelta;
2132 }
2133 for (i = colCount - 1; i >= 0; i--) {
2134 // For each rect, we clip to the rect, and then we adjust our coords.
2135 LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
2136 columnBlock->flipForWritingMode(colRect);
2137 LayoutUnit currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect .y()) - logicalLeft;
2138 LayoutUnit blockDelta = (isHorizontal ? colRect.height() : colRect.widt h());
2139 if (columnBlock->style()->isFlippedBlocksWritingMode())
2140 currLogicalTopOffset -= blockDelta;
2141 else
2142 currLogicalTopOffset += blockDelta;
2143
2144 LayoutSize offset;
2145 if (isHorizontal) {
2146 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2147 offset = LayoutSize(currLogicalLeftOffset, currLogicalTopOffset) ;
2148 else
2149 offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - colu mnBlock->borderTop() - columnBlock->paddingTop());
2150 } else {
2151 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
2152 offset = LayoutSize(currLogicalTopOffset, currLogicalLeftOffset) ;
2153 else
2154 offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnB lock->borderLeft() - columnBlock->paddingLeft(), 0);
2155 }
2156
2157 colRect.moveBy(layerOffset);
2158
2159 LayoutRect localClipRect(hitTestRect);
2160 localClipRect.intersect(colRect);
2161
2162 if (!localClipRect.isEmpty() && hitTestLocation.intersects(localClipRect )) {
2163 RenderLayer* hitLayer = 0;
2164 if (!columnIndex) {
2165 // Apply a translation transform to change where the layer paint s.
2166 TransformationMatrix oldTransform;
2167 bool oldHasTransform = childLayer->transform();
2168 if (oldHasTransform)
2169 oldTransform = *childLayer->transform();
2170 TransformationMatrix newTransform(oldTransform);
2171 newTransform.translateRight(offset.width(), offset.height());
2172
2173 childLayer->m_transform = adoptPtr(new TransformationMatrix(newT ransform));
2174 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestLocation, false, transformState, zOffset) ;
2175 if (oldHasTransform)
2176 childLayer->m_transform = adoptPtr(new TransformationMatrix( oldTransform));
2177 else
2178 childLayer->m_transform.clear();
2179 } else {
2180 // Adjust the transform such that the renderer's upper left corn er will be at (0,0) in user space.
2181 // This involves subtracting out the position of the layer in ou r current coordinate space.
2182 RenderLayer* nextLayer = columnLayers[columnIndex - 1];
2183 RefPtr<HitTestingTransformState> newTransformState = nextLayer-> createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestLocation, transformState);
2184 newTransformState->translate(offset.width(), offset.height(), Hi tTestingTransformState::AccumulateTransform);
2185 FloatPoint localPoint = newTransformState->mappedPoint();
2186 FloatQuad localPointQuad = newTransformState->mappedQuad();
2187 LayoutRect localHitTestRect = newTransformState->mappedArea().en closingBoundingBox();
2188 HitTestLocation newHitTestLocation;
2189 if (hitTestLocation.isRectBasedTest())
2190 newHitTestLocation = HitTestLocation(localPoint, localPointQ uad);
2191 else
2192 newHitTestLocation = HitTestLocation(localPoint);
2193 newTransformState->flatten();
2194
2195 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[col umnIndex - 1], request, result, localHitTestRect, newHitTestLocation,
2196 newTransformState.get(), zOf fset, columnLayers, columnIndex - 1);
2197 }
2198
2199 if (hitLayer)
2200 return hitLayer;
2201 }
2202 }
2203
2204 return 0;
2205 }
2206
2207 void RenderLayer::blockSelectionGapsBoundsChanged()
2208 {
2209 setNeedsCompositingInputsUpdate();
2210 }
2211
2212 void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
2213 {
2214 m_blockSelectionGapsBounds.unite(enclosingIntRect(bounds));
2215 blockSelectionGapsBoundsChanged();
2216 }
2217
2218 void RenderLayer::clearBlockSelectionGapsBounds()
2219 {
2220 m_blockSelectionGapsBounds = IntRect();
2221 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
2222 child->clearBlockSelectionGapsBounds();
2223 blockSelectionGapsBoundsChanged();
2224 }
2225
2226 void RenderLayer::invalidatePaintForBlockSelectionGaps()
2227 {
2228 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
2229 child->invalidatePaintForBlockSelectionGaps();
2230
2231 if (m_blockSelectionGapsBounds.isEmpty())
2232 return;
2233
2234 LayoutRect rect = m_blockSelectionGapsBounds;
2235 if (renderer()->hasOverflowClip()) {
2236 RenderBox* box = renderBox();
2237 rect.move(-box->scrolledContentOffset());
2238 if (!scrollableArea()->usesCompositedScrolling())
2239 rect.intersect(box->overflowClipRect(LayoutPoint()));
2240 }
2241 if (renderer()->hasClip())
2242 rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint()));
2243 if (!rect.isEmpty())
2244 renderer()->invalidatePaintRectangle(rect);
2245 }
2246
2247 IntRect RenderLayer::blockSelectionGapsBounds() const
2248 {
2249 if (!renderer()->isRenderBlockFlow())
2250 return IntRect();
2251
2252 RenderBlockFlow* renderBlockFlow = toRenderBlockFlow(renderer());
2253 LayoutRect gapRects = renderBlockFlow->selectionGapRectsForPaintInvalidation (renderBlockFlow);
2254
2255 return pixelSnappedIntRect(gapRects);
2256 }
2257
2258 bool RenderLayer::hasBlockSelectionGapBounds() const
2259 {
2260 // FIXME: it would be more accurate to return !blockSelectionGapsBounds().is Empty(), but this is impossible
2261 // at the moment because it causes invalid queries to layout-dependent code (crbug.com/372802).
2262 // ASSERT(renderer()->document().lifecycle().state() >= DocumentLifecycle::L ayoutClean);
2263
2264 if (!renderer()->isRenderBlock())
2265 return false;
2266
2267 return toRenderBlock(renderer())->shouldPaintSelectionGaps();
2268 }
2269
2270 bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const Layo utRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromR oot) const
2271 {
2272 // Always examine the canvas and the root.
2273 // FIXME: Could eliminate the isDocumentElement() check if we fix background painting so that the RenderView
2274 // paints the root's background.
2275 if (isRootLayer() || renderer()->isDocumentElement())
2276 return true;
2277
2278 // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
2279 // can go ahead and return true.
2280 RenderView* view = renderer()->view();
2281 ASSERT(view);
2282 if (view && !renderer()->isRenderInline()) {
2283 if (layerBounds.intersects(damageRect))
2284 return true;
2285 }
2286
2287 // Otherwise we need to compute the bounding box of this single layer and se e if it intersects
2288 // the damage rect.
2289 return physicalBoundingBox(rootLayer, offsetFromRoot).intersects(damageRect) ;
2290 }
2291
2292 LayoutRect RenderLayer::logicalBoundingBox() const
2293 {
2294 // There are three special cases we need to consider.
2295 // (1) Inline Flows. For inline flows we will create a bounding box that fu lly encompasses all of the lines occupied by the
2296 // inline. In other words, if some <span> wraps to three lines, we'll creat e a bounding box that fully encloses the
2297 // line boxes of all three lines (including overflow on those lines).
2298 // (2) Left/Top Overflow. The width/height of layers already includes right /bottom overflow. However, in the case of left/top
2299 // overflow, we have to create a bounding box that will extend to include th is overflow.
2300 // (3) Floats. When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
2301 // as part of our bounding box. We do this because we are the responsible l ayer for both hit testing and painting those
2302 // floats.
2303 LayoutRect result;
2304 if (renderer()->isInline() && renderer()->isRenderInline()) {
2305 result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
2306 } else if (renderer()->isTableRow()) {
2307 // Our bounding box is just the union of all of our cells' border/overfl ow rects.
2308 for (RenderObject* child = renderer()->slowFirstChild(); child; child = child->nextSibling()) {
2309 if (child->isTableCell()) {
2310 LayoutRect bbox = toRenderBox(child)->borderBoxRect();
2311 result.unite(bbox);
2312 LayoutRect overflowRect = renderBox()->visualOverflowRect();
2313 if (bbox != overflowRect)
2314 result.unite(overflowRect);
2315 }
2316 }
2317 } else {
2318 RenderBox* box = renderBox();
2319 ASSERT(box);
2320 result = box->borderBoxRect();
2321 result.unite(box->visualOverflowRect());
2322 }
2323
2324 ASSERT(renderer()->view());
2325 return result;
2326 }
2327
2328 static inline LayoutRect flippedLogicalBoundingBox(LayoutRect boundingBox, Rende rObject* renderer)
2329 {
2330 LayoutRect result = boundingBox;
2331 if (renderer->isBox())
2332 toRenderBox(renderer)->flipForWritingMode(result);
2333 else
2334 renderer->containingBlock()->flipForWritingMode(result);
2335 return result;
2336 }
2337
2338 LayoutRect RenderLayer::physicalBoundingBox(const RenderLayer* ancestorLayer, co nst LayoutPoint* offsetFromRoot) const
2339 {
2340 LayoutRect result = flippedLogicalBoundingBox(logicalBoundingBox(), renderer ());
2341 if (offsetFromRoot)
2342 result.moveBy(*offsetFromRoot);
2343 else
2344 convertToLayerCoords(ancestorLayer, result);
2345 return result;
2346 }
2347
2348 LayoutRect RenderLayer::fragmentsBoundingBox(const RenderLayer* ancestorLayer) c onst
2349 {
2350 if (!enclosingPaginationLayer())
2351 return physicalBoundingBox(ancestorLayer);
2352
2353 LayoutRect result = flippedLogicalBoundingBox(logicalBoundingBox(), renderer ());
2354 convertFromFlowThreadToVisualBoundingBoxInAncestor(this, ancestorLayer, resu lt);
2355 return result;
2356 }
2357
2358 LayoutRect RenderLayer::boundingBoxForCompositingOverlapTest() const
2359 {
2360 return overlapBoundsIncludeChildren() ? boundingBoxForCompositing() : fragme ntsBoundingBox(this);
2361 }
2362
2363 static void expandRectForReflectionAndStackingChildren(const RenderLayer* ancest orLayer, RenderLayer::CalculateBoundsOptions options, LayoutRect& result)
2364 {
2365 if (ancestorLayer->reflectionInfo() && !ancestorLayer->reflectionInfo()->ref lectionLayer()->hasCompositedLayerMapping())
2366 result.unite(ancestorLayer->reflectionInfo()->reflectionLayer()->boundin gBoxForCompositing(ancestorLayer));
2367
2368 ASSERT(ancestorLayer->stackingNode()->isStackingContext() || !ancestorLayer- >stackingNode()->hasPositiveZOrderList());
2369
2370 #if ENABLE(ASSERT)
2371 LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(ancestorL ayer)->stackingNode());
2372 #endif
2373
2374 RenderLayerStackingNodeIterator iterator(*ancestorLayer->stackingNode(), All Children);
2375 while (RenderLayerStackingNode* node = iterator.next()) {
2376 // Here we exclude both directly composited layers and squashing layers
2377 // because those RenderLayers don't paint into the graphics layer
2378 // for this RenderLayer. For example, the bounds of squashed RenderLayer s
2379 // will be included in the computation of the appropriate squashing
2380 // GraphicsLayer.
2381 if (options != RenderLayer::ApplyBoundsChickenEggHacks && node->layer()- >compositingState() != NotComposited)
2382 continue;
2383 result.unite(node->layer()->boundingBoxForCompositing(ancestorLayer, opt ions));
2384 }
2385 }
2386
2387 LayoutRect RenderLayer::physicalBoundingBoxIncludingReflectionAndStackingChildre n(const RenderLayer* ancestorLayer, const LayoutPoint& offsetFromRoot) const
2388 {
2389 LayoutPoint origin;
2390 LayoutRect result = physicalBoundingBox(ancestorLayer, &origin);
2391
2392 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded();
2393
2394 expandRectForReflectionAndStackingChildren(this, DoNotApplyBoundsChickenEggH acks, result);
2395
2396 result.moveBy(offsetFromRoot);
2397 return result;
2398 }
2399
2400 LayoutRect RenderLayer::boundingBoxForCompositing(const RenderLayer* ancestorLay er, CalculateBoundsOptions options) const
2401 {
2402 if (!isSelfPaintingLayer())
2403 return LayoutRect();
2404
2405 if (!ancestorLayer)
2406 ancestorLayer = this;
2407
2408 // FIXME: This could be improved to do a check like hasVisibleNonCompositing DescendantLayers() (bug 92580).
2409 if (this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant() )
2410 return LayoutRect();
2411
2412 // The root layer is always just the size of the document.
2413 if (isRootLayer())
2414 return m_renderer->view()->unscaledDocumentRect();
2415
2416 // The layer created for the RenderFlowThread is just a helper for painting and hit-testing,
2417 // and should not contribute to the bounding box. The RenderMultiColumnSets will contribute
2418 // the correct size for the rendered content of the multicol container.
2419 if (useRegionBasedColumns() && renderer()->isRenderFlowThread())
2420 return LayoutRect();
2421
2422 LayoutRect result = clipper().localClipRect();
2423 if (result == LayoutRect::infiniteIntRect()) {
2424 LayoutPoint origin;
2425 result = physicalBoundingBox(ancestorLayer, &origin);
2426
2427 const_cast<RenderLayer*>(this)->stackingNode()->updateLayerListsIfNeeded ();
2428
2429 // Reflections are implemented with RenderLayers that hang off of the re flected layer. However,
2430 // the reflection layer subtree does not include the subtree of the pare nt RenderLayer, so
2431 // a recursive computation of stacking children yields no results. This breaks cases when there are stacking
2432 // children of the parent, that need to be included in reflected composi ted bounds.
2433 // Fix this by including composited bounds of stacking children of the r eflected RenderLayer.
2434 if (hasCompositedLayerMapping() && parent() && parent()->reflectionInfo( ) && parent()->reflectionInfo()->reflectionLayer() == this)
2435 expandRectForReflectionAndStackingChildren(parent(), options, result );
2436 else
2437 expandRectForReflectionAndStackingChildren(this, options, result);
2438
2439 // FIXME: We can optimize the size of the composited layers, by not enla rging
2440 // filtered areas with the outsets if we know that the filter is going t o render in hardware.
2441 // https://bugs.webkit.org/show_bug.cgi?id=81239
2442 result.expand(m_renderer->style()->filterOutsets());
2443 }
2444
2445 if (paintsWithTransform(PaintBehaviorNormal) || (options == ApplyBoundsChick enEggHacks && transform()))
2446 result = transform()->mapRect(result);
2447
2448 if (enclosingPaginationLayer()) {
2449 convertFromFlowThreadToVisualBoundingBoxInAncestor(this, ancestorLayer, result);
2450 return result;
2451 }
2452 LayoutPoint delta;
2453 convertToLayerCoords(ancestorLayer, delta);
2454 result.moveBy(delta);
2455 return result;
2456 }
2457
2458 CompositingState RenderLayer::compositingState() const
2459 {
2460 ASSERT(isAllowedToQueryCompositingState());
2461
2462 // This is computed procedurally so there is no redundant state variable tha t
2463 // can get out of sync from the real actual compositing state.
2464
2465 if (m_groupedMapping) {
2466 ASSERT(!m_compositedLayerMapping);
2467 return PaintsIntoGroupedBacking;
2468 }
2469
2470 if (!m_compositedLayerMapping)
2471 return NotComposited;
2472
2473 return PaintsIntoOwnBacking;
2474 }
2475
2476 bool RenderLayer::isAllowedToQueryCompositingState() const
2477 {
2478 if (gCompositingQueryMode == CompositingQueriesAreAllowed)
2479 return true;
2480 return renderer()->document().lifecycle().state() >= DocumentLifecycle::InCo mpositingUpdate;
2481 }
2482
2483 CompositedLayerMapping* RenderLayer::compositedLayerMapping() const
2484 {
2485 ASSERT(isAllowedToQueryCompositingState());
2486 return m_compositedLayerMapping.get();
2487 }
2488
2489 GraphicsLayer* RenderLayer::graphicsLayerBacking() const
2490 {
2491 switch (compositingState()) {
2492 case NotComposited:
2493 return 0;
2494 case PaintsIntoGroupedBacking:
2495 return groupedMapping()->squashingLayer();
2496 default:
2497 return compositedLayerMapping()->mainGraphicsLayer();
2498 }
2499 }
2500
2501 GraphicsLayer* RenderLayer::graphicsLayerBackingForScrolling() const
2502 {
2503 switch (compositingState()) {
2504 case NotComposited:
2505 return 0;
2506 case PaintsIntoGroupedBacking:
2507 return groupedMapping()->squashingLayer();
2508 default:
2509 return compositedLayerMapping()->scrollingContentsLayer() ? compositedLa yerMapping()->scrollingContentsLayer() : compositedLayerMapping()->mainGraphicsL ayer();
2510 }
2511 }
2512
2513 void RenderLayer::ensureCompositedLayerMapping()
2514 {
2515 if (m_compositedLayerMapping)
2516 return;
2517
2518 m_compositedLayerMapping = adoptPtr(new CompositedLayerMapping(*this));
2519 m_compositedLayerMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSub tree);
2520
2521 updateOrRemoveFilterEffectRenderer();
2522 }
2523
2524 void RenderLayer::clearCompositedLayerMapping(bool layerBeingDestroyed)
2525 {
2526 if (!layerBeingDestroyed) {
2527 // We need to make sure our decendants get a geometry update. In princip le,
2528 // we could call setNeedsGraphicsLayerUpdate on our children, but that w ould
2529 // require walking the z-order lists to find them. Instead, we over-inva lidate
2530 // by marking our parent as needing a geometry update.
2531 if (RenderLayer* compositingParent = enclosingLayerWithCompositedLayerMa pping(ExcludeSelf))
2532 compositingParent->compositedLayerMapping()->setNeedsGraphicsLayerUp date(GraphicsLayerUpdateSubtree);
2533 }
2534
2535 m_compositedLayerMapping.clear();
2536
2537 if (!layerBeingDestroyed)
2538 updateOrRemoveFilterEffectRenderer();
2539 }
2540
2541 void RenderLayer::setGroupedMapping(CompositedLayerMapping* groupedMapping, bool layerBeingDestroyed)
2542 {
2543 if (groupedMapping == m_groupedMapping)
2544 return;
2545
2546 if (!layerBeingDestroyed && m_groupedMapping) {
2547 m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree );
2548 m_groupedMapping->removeRenderLayerFromSquashingGraphicsLayer(this);
2549 }
2550 m_groupedMapping = groupedMapping;
2551 if (!layerBeingDestroyed && m_groupedMapping)
2552 m_groupedMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateSubtree );
2553 }
2554
2555 bool RenderLayer::hasCompositedMask() const
2556 {
2557 return m_compositedLayerMapping && m_compositedLayerMapping->hasMaskLayer();
2558 }
2559
2560 bool RenderLayer::hasCompositedClippingMask() const
2561 {
2562 return m_compositedLayerMapping && m_compositedLayerMapping->hasChildClippin gMaskLayer();
2563 }
2564
2565 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
2566 {
2567 return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayer s) || compositingState() != PaintsIntoOwnBacking);
2568 }
2569
2570 bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
2571 {
2572 if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
2573 return false;
2574
2575 if (paintsWithTransparency(PaintBehaviorNormal))
2576 return false;
2577
2578 // We can't use hasVisibleContent(), because that will be true if our render er is hidden, but some child
2579 // is visible and that child doesn't cover the entire rect.
2580 if (renderer()->style()->visibility() != VISIBLE)
2581 return false;
2582
2583 if (paintsWithFilters() && renderer()->style()->filter().hasFilterThatAffect sOpacity())
2584 return false;
2585
2586 // FIXME: Handle simple transforms.
2587 if (paintsWithTransform(PaintBehaviorNormal))
2588 return false;
2589
2590 // FIXME: Remove this check.
2591 // This function should not be called when layer-lists are dirty.
2592 // It is somehow getting triggered during style update.
2593 if (m_stackingNode->zOrderListsDirty() || m_stackingNode->normalFlowListDirt y())
2594 return false;
2595
2596 // FIXME: We currently only check the immediate renderer,
2597 // which will miss many cases.
2598 if (renderer()->backgroundIsKnownToBeOpaqueInRect(localRect))
2599 return true;
2600
2601 // We can't consult child layers if we clip, since they might cover
2602 // parts of the rect that are clipped out.
2603 if (renderer()->hasOverflowClip())
2604 return false;
2605
2606 return childBackgroundIsKnownToBeOpaqueInRect(localRect);
2607 }
2608
2609 bool RenderLayer::childBackgroundIsKnownToBeOpaqueInRect(const LayoutRect& local Rect) const
2610 {
2611 RenderLayerStackingNodeReverseIterator revertseIterator(*m_stackingNode, Pos itiveZOrderChildren | NormalFlowChildren | NegativeZOrderChildren);
2612 while (RenderLayerStackingNode* child = revertseIterator.next()) {
2613 const RenderLayer* childLayer = child->layer();
2614 // Stop at composited paint boundaries.
2615 if (childLayer->isPaintInvalidationContainer())
2616 continue;
2617
2618 if (!childLayer->canUseConvertToLayerCoords())
2619 continue;
2620
2621 LayoutPoint childOffset;
2622 LayoutRect childLocalRect(localRect);
2623 childLayer->convertToLayerCoords(this, childOffset);
2624 childLocalRect.moveBy(-childOffset);
2625
2626 if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
2627 return true;
2628 }
2629 return false;
2630 }
2631
2632 bool RenderLayer::shouldBeSelfPaintingLayer() const
2633 {
2634 if (renderer()->isRenderPart() && toRenderPart(renderer())->requiresAccelera tedCompositing())
2635 return true;
2636 return m_layerType == NormalLayer
2637 || (m_scrollableArea && m_scrollableArea->hasOverlayScrollbars())
2638 || needsCompositedScrolling();
2639 }
2640
2641 void RenderLayer::updateSelfPaintingLayer()
2642 {
2643 bool isSelfPaintingLayer = shouldBeSelfPaintingLayer();
2644 if (this->isSelfPaintingLayer() == isSelfPaintingLayer)
2645 return;
2646
2647 m_isSelfPaintingLayer = isSelfPaintingLayer;
2648
2649 if (parent())
2650 parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
2651 }
2652
2653 bool RenderLayer::hasNonEmptyChildRenderers() const
2654 {
2655 // Some HTML can cause whitespace text nodes to have renderers, like:
2656 // <div>
2657 // <img src=...>
2658 // </div>
2659 // so test for 0x0 RenderTexts here
2660 for (RenderObject* child = renderer()->slowFirstChild(); child; child = chil d->nextSibling()) {
2661 if (!child->hasLayer()) {
2662 if (child->isRenderInline() || !child->isBox())
2663 return true;
2664
2665 if (!toRenderBox(child)->size().isEmpty())
2666 return true;
2667 }
2668 }
2669 return false;
2670 }
2671
2672 bool RenderLayer::hasBoxDecorationsOrBackground() const
2673 {
2674 return renderer()->style()->hasBoxDecorations() || renderer()->style()->hasB ackground();
2675 }
2676
2677 bool RenderLayer::hasVisibleBoxDecorations() const
2678 {
2679 if (!hasVisibleContent())
2680 return false;
2681
2682 return hasBoxDecorationsOrBackground() || hasOverflowControls();
2683 }
2684
2685 void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
2686 {
2687 if (!newStyle->hasFilter() && (!oldStyle || !oldStyle->hasFilter()))
2688 return;
2689
2690 updateOrRemoveFilterClients();
2691 updateOrRemoveFilterEffectRenderer();
2692 }
2693
2694 bool RenderLayer::attemptDirectCompositingUpdate(StyleDifference diff, const Ren derStyle* oldStyle)
2695 {
2696 CompositingReasons oldPotentialCompositingReasonsFromStyle = m_potentialComp ositingReasonsFromStyle;
2697 compositor()->updatePotentialCompositingReasonsFromStyle(this);
2698
2699 // This function implements an optimization for transforms and opacity.
2700 // A common pattern is for a touchmove handler to update the transform
2701 // and/or an opacity of an element every frame while the user moves their
2702 // finger across the screen. The conditions below recognize when the
2703 // compositing state is set up to receive a direct transform or opacity
2704 // update.
2705
2706 if (!diff.hasAtMostPropertySpecificDifferences(StyleDifference::TransformCha nged | StyleDifference::OpacityChanged))
2707 return false;
2708 // The potentialCompositingReasonsFromStyle could have changed without
2709 // a corresponding StyleDifference if an animation started or ended.
2710 if (m_potentialCompositingReasonsFromStyle != oldPotentialCompositingReasons FromStyle)
2711 return false;
2712 // We could add support for reflections if we updated the transform on
2713 // the reflection layers.
2714 if (renderer()->hasReflection())
2715 return false;
2716 // If we're unwinding a scheduleSVGFilterLayerUpdateHack(), then we can't
2717 // perform a direct compositing update because the filters code is going
2718 // to produce different output this time around. We can remove this code
2719 // once we fix the chicken/egg bugs in the filters code and delete the
2720 // scheduleSVGFilterLayerUpdateHack().
2721 if (renderer()->node() && renderer()->node()->svgFilterNeedsLayerUpdate())
2722 return false;
2723 if (!m_compositedLayerMapping)
2724 return false;
2725
2726 // To cut off almost all the work in the compositing update for
2727 // this case, we treat inline transforms has having assumed overlap
2728 // (similar to how we treat animated transforms). Notice that we read
2729 // CompositingReasonInlineTransform from the m_compositingReasons, which
2730 // means that the inline transform actually triggered assumed overlap in
2731 // the overlap map.
2732 if (diff.transformChanged() && !(m_compositingReasons & CompositingReasonInl ineTransform))
2733 return false;
2734
2735 // We composite transparent RenderLayers differently from non-transparent
2736 // RenderLayers even when the non-transparent RenderLayers are already a
2737 // stacking context.
2738 if (diff.opacityChanged() && m_renderer->style()->hasOpacity() != oldStyle-> hasOpacity())
2739 return false;
2740
2741 updateTransform(oldStyle, renderer()->style());
2742
2743 // FIXME: Consider introducing a smaller graphics layer update scope
2744 // that just handles transforms and opacity. GraphicsLayerUpdateLocal
2745 // will also program bounds, clips, and many other properties that could
2746 // not possibly have changed.
2747 m_compositedLayerMapping->setNeedsGraphicsLayerUpdate(GraphicsLayerUpdateLoc al);
2748 compositor()->setNeedsCompositingUpdate(CompositingUpdateAfterGeometryChange );
2749 return true;
2750 }
2751
2752 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle )
2753 {
2754 if (attemptDirectCompositingUpdate(diff, oldStyle))
2755 return;
2756
2757 m_stackingNode->updateIsNormalFlowOnly();
2758 m_stackingNode->updateStackingNodesAfterStyleChange(oldStyle);
2759
2760 if (m_scrollableArea)
2761 m_scrollableArea->updateAfterStyleChange(oldStyle);
2762
2763 // Overlay scrollbars can make this layer self-painting so we need
2764 // to recompute the bit once scrollbars have been updated.
2765 updateSelfPaintingLayer();
2766
2767 if (!oldStyle || !renderer()->style()->reflectionDataEquivalent(oldStyle)) {
2768 ASSERT(!oldStyle || diff.needsFullLayout());
2769 updateReflectionInfo(oldStyle);
2770 }
2771
2772 updateDescendantDependentFlags();
2773
2774 updateTransform(oldStyle, renderer()->style());
2775 updateFilters(oldStyle, renderer()->style());
2776
2777 setNeedsCompositingInputsUpdate();
2778 }
2779
2780 bool RenderLayer::scrollsOverflow() const
2781 {
2782 if (RenderLayerScrollableArea* scrollableArea = this->scrollableArea())
2783 return scrollableArea->scrollsOverflow();
2784
2785 return false;
2786 }
2787
2788 FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
2789 {
2790 const FilterOperations& filters = style->filter();
2791 if (filters.hasReferenceFilter()) {
2792 for (size_t i = 0; i < filters.size(); ++i) {
2793 FilterOperation* filterOperation = filters.operations().at(i).get();
2794 if (filterOperation->type() != FilterOperation::REFERENCE)
2795 continue;
2796 ReferenceFilterOperation* referenceOperation = toReferenceFilterOper ation(filterOperation);
2797 // FIXME: Cache the ReferenceFilter if it didn't change.
2798 RefPtrWillBeRawPtr<ReferenceFilter> referenceFilter = ReferenceFilte r::create(style->effectiveZoom());
2799 referenceFilter->setLastEffect(ReferenceFilterBuilder::build(referen ceFilter.get(), renderer(), referenceFilter->sourceGraphic(),
2800 referenceOperation));
2801 referenceOperation->setFilter(referenceFilter.release());
2802 }
2803 }
2804
2805 return filters;
2806 }
2807
2808 void RenderLayer::updateOrRemoveFilterClients()
2809 {
2810 if (!hasFilter()) {
2811 removeFilterInfoIfNeeded();
2812 return;
2813 }
2814
2815 if (renderer()->style()->filter().hasReferenceFilter())
2816 ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->fi lter());
2817 else if (hasFilterInfo())
2818 filterInfo()->removeReferenceFilterClients();
2819 }
2820
2821 void RenderLayer::updateOrRemoveFilterEffectRenderer()
2822 {
2823 // FilterEffectRenderer is only used to render the filters in software mode,
2824 // so we always need to run updateOrRemoveFilterEffectRenderer after the com posited
2825 // mode might have changed for this layer.
2826 if (!paintsWithFilters()) {
2827 // Don't delete the whole filter info here, because we might use it
2828 // for loading CSS shader files.
2829 if (RenderLayerFilterInfo* filterInfo = this->filterInfo())
2830 filterInfo->setRenderer(nullptr);
2831
2832 return;
2833 }
2834
2835 RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
2836 if (!filterInfo->renderer()) {
2837 RefPtrWillBeRawPtr<FilterEffectRenderer> filterRenderer = FilterEffectRe nderer::create();
2838 filterInfo->setRenderer(filterRenderer.release());
2839 }
2840
2841 // If the filter fails to build, remove it from the layer. It will still att empt to
2842 // go through regular processing (e.g. compositing), but never apply anythin g.
2843 if (!filterInfo->renderer()->build(renderer(), computeFilterOperations(rende rer()->style())))
2844 filterInfo->setRenderer(nullptr);
2845 }
2846
2847 void RenderLayer::filterNeedsPaintInvalidation()
2848 {
2849 {
2850 DeprecatedScheduleStyleRecalcDuringLayout marker(renderer()->document(). lifecycle());
2851 // It's possible for scheduleSVGFilterLayerUpdateHack to schedule a styl e recalc, which
2852 // is a problem because this function can be called while performing lay out.
2853 // Presumably this represents an illegal data flow of layout or composit ing
2854 // information into the style system.
2855 toElement(renderer()->node())->scheduleSVGFilterLayerUpdateHack();
2856 }
2857
2858 renderer()->setShouldDoFullPaintInvalidation();
2859 }
2860
2861 void RenderLayer::addLayerHitTestRects(LayerHitTestRects& rects) const
2862 {
2863 computeSelfHitTestRects(rects);
2864 for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
2865 child->addLayerHitTestRects(rects);
2866 }
2867
2868 void RenderLayer::computeSelfHitTestRects(LayerHitTestRects& rects) const
2869 {
2870 if (!size().isEmpty()) {
2871 Vector<LayoutRect> rect;
2872
2873 if (renderBox() && renderBox()->scrollsOverflow()) {
2874 // For scrolling layers, rects are taken to be in the space of the c ontents.
2875 // We need to include the bounding box of the layer in the space of its parent
2876 // (eg. for border / scroll bars) and if it's composited then the en tire contents
2877 // as well as they may be on another composited layer. Skip reportin g contents
2878 // for non-composited layers as they'll get projected to the same la yer as the
2879 // bounding box.
2880 if (compositingState() != NotComposited)
2881 rect.append(m_scrollableArea->overflowRect());
2882
2883 rects.set(this, rect);
2884 if (const RenderLayer* parentLayer = parent()) {
2885 LayerHitTestRects::iterator iter = rects.find(parentLayer);
2886 if (iter == rects.end()) {
2887 rects.add(parentLayer, Vector<LayoutRect>()).storedValue->va lue.append(physicalBoundingBox(parentLayer));
2888 } else {
2889 iter->value.append(physicalBoundingBox(parentLayer));
2890 }
2891 }
2892 } else {
2893 rect.append(logicalBoundingBox());
2894 rects.set(this, rect);
2895 }
2896 }
2897 }
2898
2899 void RenderLayer::setShouldDoFullPaintInvalidationIncludingNonCompositingDescend ants()
2900 {
2901 renderer()->setShouldDoFullPaintInvalidation();
2902
2903 // Disable for reading compositingState() in isPaintInvalidationContainer() below.
2904 DisableCompositingQueryAsserts disabler;
2905
2906 for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
2907 if (!child->isPaintInvalidationContainer())
2908 child->setShouldDoFullPaintInvalidationIncludingNonCompositingDescen dants();
2909 }
2910 }
2911
2912 DisableCompositingQueryAsserts::DisableCompositingQueryAsserts()
2913 : m_disabler(gCompositingQueryMode, CompositingQueriesAreAllowed) { }
2914
2915 } // namespace blink
2916
2917 #ifndef NDEBUG
2918 void showLayerTree(const blink::RenderLayer* layer)
2919 {
2920 if (!layer)
2921 return;
2922
2923 if (blink::LocalFrame* frame = layer->renderer()->frame()) {
2924 WTF::String output = externalRepresentation(frame, blink::LayoutAsTextSh owAllLayers | blink::LayoutAsTextShowLayerNesting | blink::LayoutAsTextShowCompo sitedLayers | blink::LayoutAsTextShowAddresses | blink::LayoutAsTextShowIDAndCla ss | blink::LayoutAsTextDontUpdateLayout | blink::LayoutAsTextShowLayoutState);
2925 fprintf(stderr, "%s\n", output.utf8().data());
2926 }
2927 }
2928
2929 void showLayerTree(const blink::RenderObject* renderer)
2930 {
2931 if (!renderer)
2932 return;
2933 showLayerTree(renderer->enclosingLayer());
2934 }
2935 #endif
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderLayer.h ('k') | Source/core/rendering/RenderLayerClipper.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698