• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
5  *
6  * Other contributors:
7  *   Robert O'Callahan <roc+@cs.cmu.edu>
8  *   David Baron <dbaron@fas.harvard.edu>
9  *   Christian Biesinger <cbiesinger@web.de>
10  *   Randall Jesup <rjesup@wgate.com>
11  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
12  *   Josh Soref <timeless@mac.com>
13  *   Boris Zbarsky <bzbarsky@mit.edu>
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28  *
29  * Alternatively, the contents of this file may be used under the terms
30  * of either the Mozilla Public License Version 1.1, found at
31  * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
32  * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
33  * (the "GPL"), in which case the provisions of the MPL or the GPL are
34  * applicable instead of those above.  If you wish to allow use of your
35  * version of this file only under the terms of one of those two
36  * licenses (the MPL or the GPL) and not to allow others to use your
37  * version of this file under the LGPL, indicate your decision by
38  * deletingthe provisions above and replace them with the notice and
39  * other provisions required by the MPL or the GPL, as the case may be.
40  * If you do not delete the provisions above, a recipient may use your
41  * version of this file under any of the LGPL, the MPL or the GPL.
42  */
43 
44 #include "config.h"
45 #include "RenderLayer.h"
46 
47 #include "CString.h"
48 #include "CSSPropertyNames.h"
49 #include "CSSStyleDeclaration.h"
50 #include "CSSStyleSelector.h"
51 #include "Document.h"
52 #include "EventHandler.h"
53 #include "EventNames.h"
54 #include "FloatPoint3D.h"
55 #include "FloatRect.h"
56 #include "FocusController.h"
57 #include "Frame.h"
58 #include "FrameTree.h"
59 #include "FrameView.h"
60 #include "Gradient.h"
61 #include "GraphicsContext.h"
62 #include "HTMLNames.h"
63 #include "HitTestRequest.h"
64 #include "HitTestResult.h"
65 #include "OverflowEvent.h"
66 #include "OverlapTestRequestClient.h"
67 #include "Page.h"
68 #include "PlatformMouseEvent.h"
69 #include "RenderArena.h"
70 #include "RenderInline.h"
71 #include "RenderMarquee.h"
72 #include "RenderReplica.h"
73 #include "RenderScrollbar.h"
74 #include "RenderScrollbarPart.h"
75 #include "RenderTheme.h"
76 #include "RenderTreeAsText.h"
77 #include "RenderView.h"
78 #include "ScaleTransformOperation.h"
79 #include "Scrollbar.h"
80 #include "ScrollbarTheme.h"
81 #include "SelectionController.h"
82 #include "TextStream.h"
83 #include "TransformationMatrix.h"
84 #include "TransformState.h"
85 #include "TranslateTransformOperation.h"
86 #include <wtf/StdLibExtras.h>
87 #include <wtf/UnusedParam.h>
88 
89 #if USE(ACCELERATED_COMPOSITING)
90 #include "RenderLayerBacking.h"
91 #include "RenderLayerCompositor.h"
92 #endif
93 
94 #if ENABLE(SVG)
95 #include "SVGNames.h"
96 #endif
97 
98 #define MIN_INTERSECT_FOR_REVEAL 32
99 
100 using namespace std;
101 
102 namespace WebCore {
103 
104 using namespace HTMLNames;
105 
106 const int MinimumWidthWhileResizing = 100;
107 const int MinimumHeightWhileResizing = 40;
108 
operator new(size_t sz,RenderArena * renderArena)109 void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
110 {
111     return renderArena->allocate(sz);
112 }
113 
operator delete(void * ptr,size_t sz)114 void ClipRects::operator delete(void* ptr, size_t sz)
115 {
116     // Stash size where destroy can find it.
117     *(size_t *)ptr = sz;
118 }
119 
destroy(RenderArena * renderArena)120 void ClipRects::destroy(RenderArena* renderArena)
121 {
122     delete this;
123 
124     // Recover the size left there for us by operator delete and free the memory.
125     renderArena->free(*(size_t *)this, this);
126 }
127 
RenderLayer(RenderBoxModelObject * renderer)128 RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
129     : m_renderer(renderer)
130     , m_parent(0)
131     , m_previous(0)
132     , m_next(0)
133     , m_first(0)
134     , m_last(0)
135     , m_relX(0)
136     , m_relY(0)
137     , m_x(0)
138     , m_y(0)
139     , m_width(0)
140     , m_height(0)
141     , m_scrollX(0)
142     , m_scrollY(0)
143     , m_scrollOriginX(0)
144     , m_scrollLeftOverflow(0)
145     , m_scrollWidth(0)
146     , m_scrollHeight(0)
147     , m_inResizeMode(false)
148     , m_posZOrderList(0)
149     , m_negZOrderList(0)
150     , m_normalFlowList(0)
151     , m_clipRects(0)
152 #ifndef NDEBUG
153     , m_clipRectsRoot(0)
154 #endif
155     , m_scrollDimensionsDirty(true)
156     , m_zOrderListsDirty(true)
157     , m_normalFlowListDirty(true)
158     , m_isNormalFlowOnly(shouldBeNormalFlowOnly())
159     , m_usedTransparency(false)
160     , m_paintingInsideReflection(false)
161     , m_inOverflowRelayout(false)
162     , m_needsFullRepaint(false)
163     , m_overflowStatusDirty(true)
164     , m_visibleContentStatusDirty(true)
165     , m_hasVisibleContent(false)
166     , m_visibleDescendantStatusDirty(false)
167     , m_hasVisibleDescendant(false)
168     , m_3DTransformedDescendantStatusDirty(true)
169     , m_has3DTransformedDescendant(false)
170 #if USE(ACCELERATED_COMPOSITING)
171     , m_hasCompositingDescendant(false)
172     , m_mustOverlapCompositedLayers(false)
173 #endif
174     , m_marquee(0)
175     , m_staticX(0)
176     , m_staticY(0)
177     , m_reflection(0)
178     , m_scrollCorner(0)
179     , m_resizer(0)
180 {
181     if (!renderer->firstChild() && renderer->style()) {
182         m_visibleContentStatusDirty = false;
183         m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
184     }
185 }
186 
~RenderLayer()187 RenderLayer::~RenderLayer()
188 {
189     if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
190         if (Frame* frame = renderer()->document()->frame())
191             frame->eventHandler()->resizeLayerDestroyed();
192     }
193 
194     destroyScrollbar(HorizontalScrollbar);
195     destroyScrollbar(VerticalScrollbar);
196 
197     // Child layers will be deleted by their corresponding render objects, so
198     // we don't need to delete them ourselves.
199 
200     delete m_posZOrderList;
201     delete m_negZOrderList;
202     delete m_normalFlowList;
203     delete m_marquee;
204 
205 #if USE(ACCELERATED_COMPOSITING)
206     clearBacking();
207 #endif
208 
209     // Make sure we have no lingering clip rects.
210     ASSERT(!m_clipRects);
211 
212     if (m_reflection)
213         removeReflection();
214 
215     if (m_scrollCorner)
216         m_scrollCorner->destroy();
217     if (m_resizer)
218         m_resizer->destroy();
219 }
220 
221 #if USE(ACCELERATED_COMPOSITING)
compositor() const222 RenderLayerCompositor* RenderLayer::compositor() const
223 {
224     ASSERT(renderer()->view());
225     return renderer()->view()->compositor();
226 }
227 
rendererContentChanged()228 void RenderLayer::rendererContentChanged()
229 {
230     // This can get called when video becomes accelerated, so the layers may change.
231     if (compositor()->updateLayerCompositingState(this))
232         compositor()->setCompositingLayersNeedRebuild();
233 
234     if (m_backing)
235         m_backing->rendererContentChanged();
236 }
237 #endif // USE(ACCELERATED_COMPOSITING)
238 
hasAcceleratedCompositing() const239 bool RenderLayer::hasAcceleratedCompositing() const
240 {
241 #if USE(ACCELERATED_COMPOSITING)
242     return compositor()->hasAcceleratedCompositing();
243 #else
244     return false;
245 #endif
246 }
247 
updateLayerPositions(UpdateLayerPositionsFlags flags)248 void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags)
249 {
250     if (flags & DoFullRepaint) {
251         renderer()->repaint();
252 #if USE(ACCELERATED_COMPOSITING)
253         flags &= ~CheckForRepaint;
254         // We need the full repaint to propagate to child layers if we are hardware compositing.
255         if (!compositor()->inCompositingMode())
256             flags &= ~DoFullRepaint;
257 #else
258         flags &= ~(CheckForRepaint | DoFullRepaint);
259 #endif
260     }
261 
262     updateLayerPosition(); // For relpositioned layers or non-positioned layers,
263                            // we need to keep in sync, since we may have shifted relative
264                            // to our parent layer.
265 
266     int x = 0;
267     int y = 0;
268     convertToLayerCoords(root(), x, y);
269     positionOverflowControls(x, y);
270 
271     updateVisibilityStatus();
272 
273     updateTransform();
274 
275     if (m_hasVisibleContent) {
276         RenderView* view = renderer()->view();
277         ASSERT(view);
278         // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
279         // from updateScrollInfoAfterLayout().
280         ASSERT(!view->layoutStateEnabled());
281 
282         RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
283         IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
284         IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
285         if (flags & CheckForRepaint) {
286             if (view && !view->printing()) {
287                 if (m_needsFullRepaint) {
288                     renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
289                     if (newRect != m_repaintRect)
290                         renderer()->repaintUsingContainer(repaintContainer, newRect);
291                 } else
292                     renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox);
293             }
294         }
295         m_repaintRect = newRect;
296         m_outlineBox = newOutlineBox;
297     } else {
298         m_repaintRect = IntRect();
299         m_outlineBox = IntRect();
300     }
301 
302     m_needsFullRepaint = false;
303 
304     // Go ahead and update the reflection's position and size.
305     if (m_reflection)
306         m_reflection->layout();
307 
308 #if USE(ACCELERATED_COMPOSITING)
309     // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
310     bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
311     if (isComposited())
312         flags &= ~IsCompositingUpdateRoot;
313 #endif
314 
315     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
316         child->updateLayerPositions(flags);
317 
318 #if USE(ACCELERATED_COMPOSITING)
319     if ((flags & UpdateCompositingLayers) && isComposited())
320         backing()->updateAfterLayout(RenderLayerBacking::CompositingChildren, isUpdateRoot);
321 #endif
322 
323     // With all our children positioned, now update our marquee if we need to.
324     if (m_marquee)
325         m_marquee->updateMarqueePosition();
326 }
327 
computeRepaintRects()328 void RenderLayer::computeRepaintRects()
329 {
330     RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
331     m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
332     m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
333 }
334 
updateTransform()335 void RenderLayer::updateTransform()
336 {
337     // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
338     // so check style too.
339     bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
340     bool had3DTransform = has3DTransform();
341 
342     bool hadTransform = m_transform;
343     if (hasTransform != hadTransform) {
344         if (hasTransform)
345             m_transform.set(new TransformationMatrix);
346         else
347             m_transform.clear();
348     }
349 
350     if (hasTransform) {
351         RenderBox* box = renderBox();
352         ASSERT(box);
353         m_transform->makeIdentity();
354         box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
355         makeMatrixRenderable(*m_transform, hasAcceleratedCompositing());
356     }
357 
358     if (had3DTransform != has3DTransform())
359         dirty3DTransformedDescendantStatus();
360 }
361 
currentTransform() const362 TransformationMatrix RenderLayer::currentTransform() const
363 {
364     if (!m_transform)
365         return TransformationMatrix();
366 
367 #if USE(ACCELERATED_COMPOSITING)
368     if (renderer()->style()->isRunningAcceleratedAnimation()) {
369         TransformationMatrix currTransform;
370         RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
371         style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
372         makeMatrixRenderable(currTransform, hasAcceleratedCompositing());
373         return currTransform;
374     }
375 #endif
376 
377     return *m_transform;
378 }
379 
renderableTransform(PaintBehavior paintBehavior) const380 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
381 {
382     if (!m_transform)
383         return TransformationMatrix();
384 
385     if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
386         TransformationMatrix matrix = *m_transform;
387         makeMatrixRenderable(matrix, false /* flatten 3d */);
388         return matrix;
389     }
390 
391     return *m_transform;
392 }
393 
setHasVisibleContent(bool b)394 void RenderLayer::setHasVisibleContent(bool b)
395 {
396     if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
397         return;
398     m_visibleContentStatusDirty = false;
399     m_hasVisibleContent = b;
400     if (m_hasVisibleContent) {
401         RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
402         m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
403         m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
404         if (!isNormalFlowOnly())
405             dirtyStackingContextZOrderLists();
406     }
407     if (parent())
408         parent()->childVisibilityChanged(m_hasVisibleContent);
409 }
410 
dirtyVisibleContentStatus()411 void RenderLayer::dirtyVisibleContentStatus()
412 {
413     m_visibleContentStatusDirty = true;
414     if (parent())
415         parent()->dirtyVisibleDescendantStatus();
416 }
417 
childVisibilityChanged(bool newVisibility)418 void RenderLayer::childVisibilityChanged(bool newVisibility)
419 {
420     if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
421         return;
422     if (newVisibility) {
423         RenderLayer* l = this;
424         while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) {
425             l->m_hasVisibleDescendant = true;
426             l = l->parent();
427         }
428     } else
429         dirtyVisibleDescendantStatus();
430 }
431 
dirtyVisibleDescendantStatus()432 void RenderLayer::dirtyVisibleDescendantStatus()
433 {
434     RenderLayer* l = this;
435     while (l && !l->m_visibleDescendantStatusDirty) {
436         l->m_visibleDescendantStatusDirty = true;
437         l = l->parent();
438     }
439 }
440 
updateVisibilityStatus()441 void RenderLayer::updateVisibilityStatus()
442 {
443     if (m_visibleDescendantStatusDirty) {
444         m_hasVisibleDescendant = false;
445         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
446             child->updateVisibilityStatus();
447             if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
448                 m_hasVisibleDescendant = true;
449                 break;
450             }
451         }
452         m_visibleDescendantStatusDirty = false;
453     }
454 
455     if (m_visibleContentStatusDirty) {
456         if (renderer()->style()->visibility() == VISIBLE)
457             m_hasVisibleContent = true;
458         else {
459             // layer may be hidden but still have some visible content, check for this
460             m_hasVisibleContent = false;
461             RenderObject* r = renderer()->firstChild();
462             while (r) {
463                 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
464                     m_hasVisibleContent = true;
465                     break;
466                 }
467                 if (r->firstChild() && !r->hasLayer())
468                     r = r->firstChild();
469                 else if (r->nextSibling())
470                     r = r->nextSibling();
471                 else {
472                     do {
473                         r = r->parent();
474                         if (r == renderer())
475                             r = 0;
476                     } while (r && !r->nextSibling());
477                     if (r)
478                         r = r->nextSibling();
479                 }
480             }
481         }
482         m_visibleContentStatusDirty = false;
483     }
484 }
485 
dirty3DTransformedDescendantStatus()486 void RenderLayer::dirty3DTransformedDescendantStatus()
487 {
488     RenderLayer* curr = stackingContext();
489     if (curr)
490         curr->m_3DTransformedDescendantStatusDirty = true;
491 
492     // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
493     // Note that preserves3D() creates stacking context, so we can just run up the stacking contexts.
494     while (curr && curr->preserves3D()) {
495         curr->m_3DTransformedDescendantStatusDirty = true;
496         curr = curr->stackingContext();
497     }
498 }
499 
500 // Return true if this layer or any preserve-3d descendants have 3d.
update3DTransformedDescendantStatus()501 bool RenderLayer::update3DTransformedDescendantStatus()
502 {
503     if (m_3DTransformedDescendantStatusDirty) {
504         m_has3DTransformedDescendant = false;
505 
506         // Transformed or preserve-3d descendants can only be in the z-order lists, not
507         // in the normal flow list, so we only need to check those.
508         if (m_posZOrderList) {
509             for (unsigned i = 0; i < m_posZOrderList->size(); ++i)
510                 m_has3DTransformedDescendant |= m_posZOrderList->at(i)->update3DTransformedDescendantStatus();
511         }
512 
513         // Now check our negative z-index children.
514         if (m_negZOrderList) {
515             for (unsigned i = 0; i < m_negZOrderList->size(); ++i)
516                 m_has3DTransformedDescendant |= m_negZOrderList->at(i)->update3DTransformedDescendantStatus();
517         }
518 
519         m_3DTransformedDescendantStatusDirty = false;
520     }
521 
522     // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
523     // the m_has3DTransformedDescendant set.
524     if (preserves3D())
525         return has3DTransform() || m_has3DTransformedDescendant;
526 
527     return has3DTransform();
528 }
529 
updateLayerPosition()530 void RenderLayer::updateLayerPosition()
531 {
532     // Clear our cached clip rect information.
533     clearClipRects();
534 
535     RenderBox* rendererBox = renderBox();
536 
537     int x = rendererBox ? rendererBox->x() : 0;
538     int y = rendererBox ? rendererBox->y() : 0;
539 
540     if (!renderer()->isPositioned() && renderer()->parent()) {
541         // We must adjust our position by walking up the render tree looking for the
542         // nearest enclosing object with a layer.
543         RenderObject* curr = renderer()->parent();
544         while (curr && !curr->hasLayer()) {
545             if (curr->isBox() && !curr->isTableRow()) {
546                 // Rows and cells share the same coordinate space (that of the section).
547                 // Omit them when computing our xpos/ypos.
548                 RenderBox* currBox = toRenderBox(curr);
549                 x += currBox->x();
550                 y += currBox->y();
551             }
552             curr = curr->parent();
553         }
554         if (curr->isBox() && curr->isTableRow()) {
555             // Put ourselves into the row coordinate space.
556             RenderBox* currBox = toRenderBox(curr);
557             x -= currBox->x();
558             y -= currBox->y();
559         }
560     }
561 
562     m_relX = m_relY = 0;
563     if (renderer()->isRelPositioned()) {
564         m_relX = renderer()->relativePositionOffsetX();
565         m_relY = renderer()->relativePositionOffsetY();
566         x += m_relX; y += m_relY;
567     }
568 
569     // Subtract our parent's scroll offset.
570     if (renderer()->isPositioned() && enclosingPositionedAncestor()) {
571         RenderLayer* positionedParent = enclosingPositionedAncestor();
572 
573         // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
574         positionedParent->subtractScrolledContentOffset(x, y);
575 
576         if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) {
577             IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer()));
578             x += offset.width();
579             y += offset.height();
580         }
581     } else if (parent())
582         parent()->subtractScrolledContentOffset(x, y);
583 
584     // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
585 
586     setLocation(x, y);
587 
588     if (renderer()->isRenderInline()) {
589         RenderInline* inlineFlow = toRenderInline(renderer());
590         IntRect lineBox = inlineFlow->linesBoundingBox();
591         setWidth(lineBox.width());
592         setHeight(lineBox.height());
593     } else if (RenderBox* box = renderBox()) {
594         setWidth(box->width());
595         setHeight(box->height());
596 
597         if (!box->hasOverflowClip()) {
598             if (box->rightLayoutOverflow() > box->width())
599                 setWidth(box->rightLayoutOverflow());
600             if (box->bottomLayoutOverflow() > box->height())
601                 setHeight(box->bottomLayoutOverflow());
602         }
603     }
604 }
605 
perspectiveTransform() const606 TransformationMatrix RenderLayer::perspectiveTransform() const
607 {
608     if (!renderer()->hasTransform())
609         return TransformationMatrix();
610 
611     RenderStyle* style = renderer()->style();
612     if (!style->hasPerspective())
613         return TransformationMatrix();
614 
615     // Maybe fetch the perspective from the backing?
616     const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
617     const float boxWidth = borderBox.width();
618     const float boxHeight = borderBox.height();
619 
620     float perspectiveOriginX = style->perspectiveOriginX().calcFloatValue(boxWidth);
621     float perspectiveOriginY = style->perspectiveOriginY().calcFloatValue(boxHeight);
622 
623     // A perspective origin of 0,0 makes the vanishing point in the center of the element.
624     // We want it to be in the top-left, so subtract half the height and width.
625     perspectiveOriginX -= boxWidth / 2.0f;
626     perspectiveOriginY -= boxHeight / 2.0f;
627 
628     TransformationMatrix t;
629     t.translate(perspectiveOriginX, perspectiveOriginY);
630     t.applyPerspective(style->perspective());
631     t.translate(-perspectiveOriginX, -perspectiveOriginY);
632 
633     return t;
634 }
635 
perspectiveOrigin() const636 FloatPoint RenderLayer::perspectiveOrigin() const
637 {
638     if (!renderer()->hasTransform())
639         return FloatPoint();
640 
641     const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
642     RenderStyle* style = renderer()->style();
643 
644     return FloatPoint(style->perspectiveOriginX().calcFloatValue(borderBox.width()),
645                       style->perspectiveOriginY().calcFloatValue(borderBox.height()));
646 }
647 
stackingContext() const648 RenderLayer* RenderLayer::stackingContext() const
649 {
650     RenderLayer* layer = parent();
651 #if ENABLE(COMPOSITED_FIXED_ELEMENTS)
652     // When using composited fixed elements, they are turned into a stacking
653     // context and we thus need to return them.
654     // We can simplify the while loop by using isStackingContext(); with
655     // composited fixed elements turned on, this will return true for them,
656     // and is otherwise equivalent to the replaced statements.
657     while (layer && !layer->renderer()->isRoot() && !layer->isStackingContext())
658 #else
659     while (layer && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex())
660 #endif
661         layer = layer->parent();
662     return layer;
663 }
664 
isPositionedContainer(RenderLayer * layer)665 static inline bool isPositionedContainer(RenderLayer* layer)
666 {
667     RenderObject* o = layer->renderer();
668     return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform();
669 }
670 
isFixedPositionedContainer(RenderLayer * layer)671 static inline bool isFixedPositionedContainer(RenderLayer* layer)
672 {
673     RenderObject* o = layer->renderer();
674     return o->isRenderView() || layer->hasTransform();
675 }
676 
enclosingPositionedAncestor() const677 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
678 {
679     RenderLayer* curr = parent();
680     while (curr && !isPositionedContainer(curr))
681         curr = curr->parent();
682 
683     return curr;
684 }
685 
enclosingTransformedAncestor() const686 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
687 {
688     RenderLayer* curr = parent();
689     while (curr && !curr->renderer()->isRenderView() && !curr->transform())
690         curr = curr->parent();
691 
692     return curr;
693 }
694 
compositingContainer(const RenderLayer * layer)695 static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
696 {
697     return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext();
698 }
699 
700 #if USE(ACCELERATED_COMPOSITING)
enclosingCompositingLayer(bool includeSelf) const701 RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
702 {
703     if (includeSelf && isComposited())
704         return const_cast<RenderLayer*>(this);
705 
706     for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
707         if (curr->isComposited())
708             return const_cast<RenderLayer*>(curr);
709     }
710 
711     return 0;
712 }
713 #endif
714 
clippingRoot() const715 RenderLayer* RenderLayer::clippingRoot() const
716 {
717     const RenderLayer* current = this;
718     while (current) {
719         if (current->renderer()->isRenderView())
720             return const_cast<RenderLayer*>(current);
721 
722         current = compositingContainer(current);
723         ASSERT(current);
724         if (current->transform()
725 #if USE(ACCELERATED_COMPOSITING)
726             || current->isComposited()
727 #endif
728         )
729             return const_cast<RenderLayer*>(current);
730     }
731 
732     ASSERT_NOT_REACHED();
733     return 0;
734 }
735 
absoluteToContents(const IntPoint & absolutePoint) const736 IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const
737 {
738     // We don't use convertToLayerCoords because it doesn't know about transforms
739     return roundedIntPoint(renderer()->absoluteToLocal(absolutePoint, false, true));
740 }
741 
requiresSlowRepaints() const742 bool RenderLayer::requiresSlowRepaints() const
743 {
744     if (isTransparent() || hasReflection() || hasTransform())
745         return true;
746     if (!parent())
747         return false;
748     return parent()->requiresSlowRepaints();
749 }
750 
isTransparent() const751 bool RenderLayer::isTransparent() const
752 {
753 #if ENABLE(SVG)
754     if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
755         return false;
756 #endif
757     return renderer()->isTransparent() || renderer()->hasMask();
758 }
759 
transparentPaintingAncestor()760 RenderLayer* RenderLayer::transparentPaintingAncestor()
761 {
762     if (isComposited())
763         return 0;
764 
765     for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
766         if (curr->isComposited())
767             return 0;
768         if (curr->isTransparent())
769             return curr;
770     }
771     return 0;
772 }
773 
774 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior);
775 
expandClipRectForDescendantsAndReflection(IntRect & clipRect,const RenderLayer * l,const RenderLayer * rootLayer,PaintBehavior paintBehavior)776 static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
777 {
778     // If we have a mask, then the clip is limited to the border box area (and there is
779     // no need to examine child layers).
780     if (!l->renderer()->hasMask()) {
781         // Note: we don't have to walk z-order lists since transparent elements always establish
782         // a stacking context.  This means we can just walk the layer tree directly.
783         for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
784             if (!l->reflection() || l->reflectionLayer() != curr)
785                 clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior));
786         }
787     }
788 
789     // If we have a reflection, then we need to account for that when we push the clip.  Reflect our entire
790     // current transparencyClipBox to catch all child layers.
791     // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
792     // size into the parent layer.
793     if (l->renderer()->hasReflection()) {
794         int deltaX = 0;
795         int deltaY = 0;
796         l->convertToLayerCoords(rootLayer, deltaX, deltaY);
797         clipRect.move(-deltaX, -deltaY);
798         clipRect.unite(l->renderBox()->reflectedRect(clipRect));
799         clipRect.move(deltaX, deltaY);
800     }
801 }
802 
transparencyClipBox(const RenderLayer * l,const RenderLayer * rootLayer,PaintBehavior paintBehavior)803 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
804 {
805     // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
806     // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
807     // would be better to respect clips.
808 
809     if (rootLayer != l && l->paintsWithTransform(paintBehavior)) {
810         // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
811         // the transformed layer and all of its children.
812         int x = 0;
813         int y = 0;
814         l->convertToLayerCoords(rootLayer, x, y);
815 
816         TransformationMatrix transform;
817         transform.translate(x, y);
818         transform = *l->transform() * transform;
819 
820         IntRect clipRect = l->boundingBox(l);
821         expandClipRectForDescendantsAndReflection(clipRect, l, l, paintBehavior);
822         return transform.mapRect(clipRect);
823     }
824 
825     IntRect clipRect = l->boundingBox(rootLayer);
826     expandClipRectForDescendantsAndReflection(clipRect, l, rootLayer, paintBehavior);
827     return clipRect;
828 }
829 
beginTransparencyLayers(GraphicsContext * p,const RenderLayer * rootLayer,PaintBehavior paintBehavior)830 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
831 {
832     if (p->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency))
833         return;
834 
835     RenderLayer* ancestor = transparentPaintingAncestor();
836     if (ancestor)
837         ancestor->beginTransparencyLayers(p, rootLayer, paintBehavior);
838 
839     if (paintsWithTransparency(paintBehavior)) {
840         m_usedTransparency = true;
841         p->save();
842         IntRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior);
843         p->clip(clipRect);
844         p->beginTransparencyLayer(renderer()->opacity());
845 #ifdef REVEAL_TRANSPARENCY_LAYERS
846         p->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), DeviceColorSpace);
847         p->fillRect(clipRect);
848 #endif
849     }
850 }
851 
operator new(size_t sz,RenderArena * renderArena)852 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
853 {
854     return renderArena->allocate(sz);
855 }
856 
operator delete(void * ptr,size_t sz)857 void RenderLayer::operator delete(void* ptr, size_t sz)
858 {
859     // Stash size where destroy can find it.
860     *(size_t *)ptr = sz;
861 }
862 
destroy(RenderArena * renderArena)863 void RenderLayer::destroy(RenderArena* renderArena)
864 {
865     delete this;
866 
867     // Recover the size left there for us by operator delete and free the memory.
868     renderArena->free(*(size_t *)this, this);
869 }
870 
addChild(RenderLayer * child,RenderLayer * beforeChild)871 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
872 {
873     RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
874     if (prevSibling) {
875         child->setPreviousSibling(prevSibling);
876         prevSibling->setNextSibling(child);
877     } else
878         setFirstChild(child);
879 
880     if (beforeChild) {
881         beforeChild->setPreviousSibling(child);
882         child->setNextSibling(beforeChild);
883     } else
884         setLastChild(child);
885 
886     child->setParent(this);
887 
888     if (child->isNormalFlowOnly())
889         dirtyNormalFlowList();
890 
891     if (!child->isNormalFlowOnly() || child->firstChild()) {
892         // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
893         // case where we're building up generated content layers.  This is ok, since the lists will start
894         // off dirty in that case anyway.
895         child->dirtyStackingContextZOrderLists();
896     }
897 
898     child->updateVisibilityStatus();
899     if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
900         childVisibilityChanged(true);
901 
902 #if USE(ACCELERATED_COMPOSITING)
903     compositor()->layerWasAdded(this, child);
904 #endif
905 }
906 
removeChild(RenderLayer * oldChild)907 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
908 {
909 #if USE(ACCELERATED_COMPOSITING)
910     if (!renderer()->documentBeingDestroyed())
911         compositor()->layerWillBeRemoved(this, oldChild);
912 #endif
913 
914     // remove the child
915     if (oldChild->previousSibling())
916         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
917     if (oldChild->nextSibling())
918         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
919 
920     if (m_first == oldChild)
921         m_first = oldChild->nextSibling();
922     if (m_last == oldChild)
923         m_last = oldChild->previousSibling();
924 
925     if (oldChild->isNormalFlowOnly())
926         dirtyNormalFlowList();
927     if (!oldChild->isNormalFlowOnly() || oldChild->firstChild()) {
928         // Dirty the z-order list in which we are contained.  When called via the
929         // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
930         // from the main layer tree, so we need to null-check the |stackingContext| value.
931         oldChild->dirtyStackingContextZOrderLists();
932     }
933 
934     oldChild->setPreviousSibling(0);
935     oldChild->setNextSibling(0);
936     oldChild->setParent(0);
937 
938     oldChild->updateVisibilityStatus();
939     if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
940         childVisibilityChanged(false);
941 
942     return oldChild;
943 }
944 
removeOnlyThisLayer()945 void RenderLayer::removeOnlyThisLayer()
946 {
947     if (!m_parent)
948         return;
949 
950     // Mark that we are about to lose our layer. This makes render tree
951     // walks ignore this layer while we're removing it.
952     m_renderer->setHasLayer(false);
953 
954 #if USE(ACCELERATED_COMPOSITING)
955     compositor()->layerWillBeRemoved(m_parent, this);
956 #endif
957 
958     // Dirty the clip rects.
959     clearClipRectsIncludingDescendants();
960 
961     // Remove us from the parent.
962     RenderLayer* parent = m_parent;
963     RenderLayer* nextSib = nextSibling();
964     parent->removeChild(this);
965 
966     if (reflection())
967         removeChild(reflectionLayer());
968 
969     // Now walk our kids and reattach them to our parent.
970     RenderLayer* current = m_first;
971     while (current) {
972         RenderLayer* next = current->nextSibling();
973         removeChild(current);
974         parent->addChild(current, nextSib);
975         current->updateLayerPositions(); // Depends on hasLayer() already being false for proper layout.
976         current = next;
977     }
978 
979     m_renderer->destroyLayer();
980 }
981 
insertOnlyThisLayer()982 void RenderLayer::insertOnlyThisLayer()
983 {
984     if (!m_parent && renderer()->parent()) {
985         // We need to connect ourselves when our renderer() has a parent.
986         // Find our enclosingLayer and add ourselves.
987         RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
988         ASSERT(parentLayer);
989         RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
990         parentLayer->addChild(this, beforeChild);
991     }
992 
993     // Remove all descendant layers from the hierarchy and add them to the new position.
994     for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
995         curr->moveLayers(m_parent, this);
996 
997     // Clear out all the clip rects.
998     clearClipRectsIncludingDescendants();
999 }
1000 
1001 void
convertToLayerCoords(const RenderLayer * ancestorLayer,int & xPos,int & yPos) const1002 RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, int& yPos) const
1003 {
1004     if (ancestorLayer == this)
1005         return;
1006 
1007     EPosition position = renderer()->style()->position();
1008     if (position == FixedPosition && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) {
1009         // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
1010         // localToAbsolute() on the RenderView.
1011         FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
1012         xPos += absPos.x();
1013         yPos += absPos.y();
1014         return;
1015     }
1016 
1017     if (position == FixedPosition) {
1018         // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
1019         // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
1020         // so we should always find the ancestor at or before we find the fixed position container.
1021         RenderLayer* fixedPositionContainerLayer = 0;
1022         bool foundAncestor = false;
1023         for (RenderLayer* currLayer = parent(); currLayer; currLayer = currLayer->parent()) {
1024             if (currLayer == ancestorLayer)
1025                 foundAncestor = true;
1026 
1027             if (isFixedPositionedContainer(currLayer)) {
1028                 fixedPositionContainerLayer = currLayer;
1029                 ASSERT(foundAncestor);
1030                 break;
1031             }
1032         }
1033 
1034         ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
1035 
1036         if (fixedPositionContainerLayer != ancestorLayer) {
1037             int fixedContainerX = 0;
1038             int fixedContainerY = 0;
1039             convertToLayerCoords(fixedPositionContainerLayer, fixedContainerX, fixedContainerY);
1040 
1041             int ancestorX = 0;
1042             int ancestorY = 0;
1043             ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorX, ancestorY);
1044 
1045             xPos += (fixedContainerX - ancestorX);
1046             yPos += (fixedContainerY - ancestorY);
1047             return;
1048         }
1049     }
1050 
1051 
1052     RenderLayer* parentLayer;
1053     if (position == AbsolutePosition || position == FixedPosition) {
1054         // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
1055         parentLayer = parent();
1056         bool foundAncestorFirst = false;
1057         while (parentLayer) {
1058             if (isPositionedContainer(parentLayer))
1059                 break;
1060 
1061             if (parentLayer == ancestorLayer) {
1062                 foundAncestorFirst = true;
1063                 break;
1064             }
1065 
1066             parentLayer = parentLayer->parent();
1067         }
1068 
1069         if (foundAncestorFirst) {
1070             // Found ancestorLayer before the abs. positioned container, so compute offset of both relative
1071             // to enclosingPositionedAncestor and subtract.
1072             RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
1073 
1074             int thisX = 0;
1075             int thisY = 0;
1076             convertToLayerCoords(positionedAncestor, thisX, thisY);
1077 
1078             int ancestorX = 0;
1079             int ancestorY = 0;
1080             ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorX, ancestorY);
1081 
1082             xPos += (thisX - ancestorX);
1083             yPos += (thisY - ancestorY);
1084             return;
1085         }
1086     } else
1087         parentLayer = parent();
1088 
1089     if (!parentLayer)
1090         return;
1091 
1092     parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos);
1093 
1094     xPos += x();
1095     yPos += y();
1096 }
1097 
adjustedScrollDelta(int beginningDelta)1098 static inline int adjustedScrollDelta(int beginningDelta) {
1099     // This implemention matches Firefox's.
1100     // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
1101     const int speedReducer = 12;
1102 
1103     int adjustedDelta = beginningDelta / speedReducer;
1104     if (adjustedDelta > 1)
1105         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1;
1106     else if (adjustedDelta < -1)
1107         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1;
1108 
1109     return adjustedDelta;
1110 }
1111 
panScrollFromPoint(const IntPoint & sourcePoint)1112 void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
1113 {
1114     Frame* frame = renderer()->document()->frame();
1115     if (!frame)
1116         return;
1117 
1118     IntPoint currentMousePosition = frame->eventHandler()->currentMousePosition();
1119 
1120     // We need to check if the current mouse position is out of the window. When the mouse is out of the window, the position is incoherent
1121     static IntPoint previousMousePosition;
1122     if (currentMousePosition.x() < 0 || currentMousePosition.y() < 0)
1123         currentMousePosition = previousMousePosition;
1124     else
1125         previousMousePosition = currentMousePosition;
1126 
1127     int xDelta = currentMousePosition.x() - sourcePoint.x();
1128     int yDelta = currentMousePosition.y() - sourcePoint.y();
1129 
1130     if (abs(xDelta) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon
1131         xDelta = 0;
1132     if (abs(yDelta) <= ScrollView::noPanScrollRadius)
1133         yDelta = 0;
1134 
1135     scrollByRecursively(adjustedScrollDelta(xDelta), adjustedScrollDelta(yDelta));
1136 }
1137 
scrollByRecursively(int xDelta,int yDelta)1138 void RenderLayer::scrollByRecursively(int xDelta, int yDelta)
1139 {
1140     if (!xDelta && !yDelta)
1141         return;
1142 
1143     bool restrictedByLineClamp = false;
1144     if (renderer()->parent())
1145         restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1146 
1147     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1148         int newOffsetX = scrollXOffset() + xDelta;
1149         int newOffsetY = scrollYOffset() + yDelta;
1150         scrollToOffset(newOffsetX, newOffsetY);
1151 
1152         // If this layer can't do the scroll we ask the next layer up that can scroll to try
1153         int leftToScrollX = newOffsetX - scrollXOffset();
1154         int leftToScrollY = newOffsetY - scrollYOffset();
1155         if ((leftToScrollX || leftToScrollY) && renderer()->parent()) {
1156             RenderObject* nextRenderer = renderer()->parent();
1157             while (nextRenderer) {
1158                 if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea()) {
1159                     nextRenderer->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY);
1160                     break;
1161                 }
1162                 nextRenderer = nextRenderer->parent();
1163             }
1164 
1165             Frame* frame = renderer()->document()->frame();
1166             if (frame)
1167                 frame->eventHandler()->updateAutoscrollRenderer();
1168         }
1169     } else if (renderer()->view()->frameView()) {
1170         // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't
1171         // have an overflow clip. Which means that it is a document node that can be scrolled.
1172         renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta));
1173         // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement?
1174         // https://bugs.webkit.org/show_bug.cgi?id=28237
1175     }
1176 }
1177 
1178 
1179 void
addScrolledContentOffset(int & x,int & y) const1180 RenderLayer::addScrolledContentOffset(int& x, int& y) const
1181 {
1182     x += scrollXOffset() + m_scrollLeftOverflow;
1183     y += scrollYOffset();
1184 }
1185 
1186 void
subtractScrolledContentOffset(int & x,int & y) const1187 RenderLayer::subtractScrolledContentOffset(int& x, int& y) const
1188 {
1189     x -= scrollXOffset() + m_scrollLeftOverflow;
1190     y -= scrollYOffset();
1191 }
1192 
scrollToOffset(int x,int y,bool updateScrollbars,bool repaint)1193 void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
1194 {
1195     RenderBox* box = renderBox();
1196     if (!box)
1197         return;
1198 
1199     if (box->style()->overflowX() != OMARQUEE) {
1200         if (x < 0) x = 0;
1201         if (y < 0) y = 0;
1202 
1203         // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
1204         // to be (for overflow:hidden blocks).
1205         int maxX = scrollWidth() - box->clientWidth();
1206         int maxY = scrollHeight() - box->clientHeight();
1207 
1208         if (x > maxX) x = maxX;
1209         if (y > maxY) y = maxY;
1210     }
1211 
1212     // FIXME: Eventually, we will want to perform a blit.  For now never
1213     // blit, since the check for blitting is going to be very
1214     // complicated (since it will involve testing whether our layer
1215     // is either occluded by another layer or clipped by an enclosing
1216     // layer or contains fixed backgrounds, etc.).
1217     int newScrollX = x - m_scrollOriginX;
1218     if (m_scrollY == y && m_scrollX == newScrollX)
1219         return;
1220     m_scrollX = newScrollX;
1221     m_scrollY = y;
1222 
1223     // Update the positions of our child layers. Don't have updateLayerPositions() update
1224     // compositing layers, because we need to do a deep update from the compositing ancestor.
1225     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
1226         child->updateLayerPositions(0);
1227 
1228 #if USE(ACCELERATED_COMPOSITING)
1229     if (compositor()->inCompositingMode()) {
1230         if (RenderLayer* compositingAncestor = ancestorCompositingLayer()) {
1231             bool isUpdateRoot = true;
1232             compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot);
1233         }
1234     }
1235 #endif
1236 
1237     RenderView* view = renderer()->view();
1238 
1239     // We should have a RenderView if we're trying to scroll.
1240     ASSERT(view);
1241     if (view) {
1242 #if ENABLE(DASHBOARD_SUPPORT)
1243         // Update dashboard regions, scrolling may change the clip of a
1244         // particular region.
1245         view->frameView()->updateDashboardRegions();
1246 #endif
1247 
1248         view->updateWidgetPositions();
1249     }
1250 
1251     // The caret rect needs to be invalidated after scrolling
1252     Frame* frame = renderer()->document()->frame();
1253     if (frame)
1254         frame->selection()->setNeedsLayout();
1255 
1256     // Just schedule a full repaint of our object.
1257     if (repaint)
1258         renderer()->repaint();
1259 
1260     if (updateScrollbars) {
1261         if (m_hBar)
1262             m_hBar->setValue(scrollXOffset());
1263         if (m_vBar)
1264             m_vBar->setValue(m_scrollY);
1265     }
1266 
1267     // Schedule the scroll DOM event.
1268     if (view) {
1269         if (FrameView* frameView = view->frameView())
1270             frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), renderer()->node());
1271     }
1272 }
1273 
scrollRectToVisible(const IntRect & rect,bool scrollToAnchor,const ScrollAlignment & alignX,const ScrollAlignment & alignY)1274 void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1275 {
1276     RenderLayer* parentLayer = 0;
1277     IntRect newRect = rect;
1278     int xOffset = 0, yOffset = 0;
1279 
1280     // We may end up propagating a scroll event. It is important that we suspend events until
1281     // the end of the function since they could delete the layer or the layer's renderer().
1282     FrameView* frameView = renderer()->document()->view();
1283     if (frameView)
1284         frameView->pauseScheduledEvents();
1285 
1286     bool restrictedByLineClamp = false;
1287     if (renderer()->parent()) {
1288         parentLayer = renderer()->parent()->enclosingLayer();
1289         restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1290     }
1291 
1292     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1293         // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
1294         // This will prevent us from revealing text hidden by the slider in Safari RSS.
1295         RenderBox* box = renderBox();
1296         ASSERT(box);
1297         FloatPoint absPos = box->localToAbsolute();
1298         absPos.move(box->borderLeft(), box->borderTop());
1299 
1300         IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight());
1301         IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
1302         IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
1303 
1304         xOffset = r.x() - absPos.x();
1305         yOffset = r.y() - absPos.y();
1306         // Adjust offsets if they're outside of the allowable range.
1307         xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
1308         yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
1309 
1310         if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {
1311             int diffX = scrollXOffset();
1312             int diffY = scrollYOffset();
1313             scrollToOffset(xOffset, yOffset);
1314             diffX = scrollXOffset() - diffX;
1315             diffY = scrollYOffset() - diffY;
1316             newRect.setX(rect.x() - diffX);
1317             newRect.setY(rect.y() - diffY);
1318         }
1319     } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) {
1320         if (frameView) {
1321             if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) {
1322                 IntRect viewRect = frameView->visibleContentRect();
1323                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
1324 
1325                 xOffset = r.x();
1326                 yOffset = r.y();
1327                 // Adjust offsets if they're outside of the allowable range.
1328                 xOffset = max(0, min(frameView->contentsWidth(), xOffset));
1329                 yOffset = max(0, min(frameView->contentsHeight(), yOffset));
1330 
1331                 frameView->setScrollPosition(IntPoint(xOffset, yOffset));
1332                 parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer();
1333                 newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
1334                 newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
1335             } else {
1336                 IntRect viewRect = frameView->visibleContentRect(true);
1337                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
1338 
1339                 // If this is the outermost view that RenderLayer needs to scroll, then we should scroll the view recursively
1340                 // Other apps, like Mail, rely on this feature.
1341                 frameView->scrollRectIntoViewRecursively(r);
1342             }
1343         }
1344     }
1345 
1346     if (parentLayer)
1347         parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY);
1348 
1349     if (frameView)
1350         frameView->resumeScheduledEvents();
1351 }
1352 
getRectToExpose(const IntRect & visibleRect,const IntRect & exposeRect,const ScrollAlignment & alignX,const ScrollAlignment & alignY)1353 IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1354 {
1355     // Determine the appropriate X behavior.
1356     ScrollBehavior scrollX;
1357     IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
1358     int intersectWidth = intersection(visibleRect, exposeRectX).width();
1359     if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
1360         // If the rectangle is fully visible, use the specified visible behavior.
1361         // If the rectangle is partially visible, but over a certain threshold,
1362         // then treat it as fully visible to avoid unnecessary horizontal scrolling
1363         scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1364     else if (intersectWidth == visibleRect.width()) {
1365         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1366         scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1367         if (scrollX == alignCenter)
1368             scrollX = noScroll;
1369     } else if (intersectWidth > 0)
1370         // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
1371         scrollX = ScrollAlignment::getPartialBehavior(alignX);
1372     else
1373         scrollX = ScrollAlignment::getHiddenBehavior(alignX);
1374     // If we're trying to align to the closest edge, and the exposeRect is further right
1375     // than the visibleRect, and not bigger than the visible area, then align with the right.
1376     if (scrollX == alignToClosestEdge && exposeRect.right() > visibleRect.right() && exposeRect.width() < visibleRect.width())
1377         scrollX = alignRight;
1378 
1379     // Given the X behavior, compute the X coordinate.
1380     int x;
1381     if (scrollX == noScroll)
1382         x = visibleRect.x();
1383     else if (scrollX == alignRight)
1384         x = exposeRect.right() - visibleRect.width();
1385     else if (scrollX == alignCenter)
1386         x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
1387     else
1388         x = exposeRect.x();
1389 
1390     // Determine the appropriate Y behavior.
1391     ScrollBehavior scrollY;
1392     IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
1393     int intersectHeight = intersection(visibleRect, exposeRectY).height();
1394     if (intersectHeight == exposeRect.height())
1395         // If the rectangle is fully visible, use the specified visible behavior.
1396         scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1397     else if (intersectHeight == visibleRect.height()) {
1398         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1399         scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1400         if (scrollY == alignCenter)
1401             scrollY = noScroll;
1402     } else if (intersectHeight > 0)
1403         // If the rectangle is partially visible, use the specified partial behavior
1404         scrollY = ScrollAlignment::getPartialBehavior(alignY);
1405     else
1406         scrollY = ScrollAlignment::getHiddenBehavior(alignY);
1407     // If we're trying to align to the closest edge, and the exposeRect is further down
1408     // than the visibleRect, and not bigger than the visible area, then align with the bottom.
1409     if (scrollY == alignToClosestEdge && exposeRect.bottom() > visibleRect.bottom() && exposeRect.height() < visibleRect.height())
1410         scrollY = alignBottom;
1411 
1412     // Given the Y behavior, compute the Y coordinate.
1413     int y;
1414     if (scrollY == noScroll)
1415         y = visibleRect.y();
1416     else if (scrollY == alignBottom)
1417         y = exposeRect.bottom() - visibleRect.height();
1418     else if (scrollY == alignCenter)
1419         y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
1420     else
1421         y = exposeRect.y();
1422 
1423     return IntRect(IntPoint(x, y), visibleRect.size());
1424 }
1425 
autoscroll()1426 void RenderLayer::autoscroll()
1427 {
1428     Frame* frame = renderer()->document()->frame();
1429     if (!frame)
1430         return;
1431 
1432     FrameView* frameView = frame->view();
1433     if (!frameView)
1434         return;
1435 
1436 #if ENABLE(DRAG_SUPPORT)
1437     frame->eventHandler()->updateSelectionForMouseDrag();
1438 #endif
1439 
1440     IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
1441     scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
1442 }
1443 
resize(const PlatformMouseEvent & evt,const IntSize & oldOffset)1444 void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
1445 {
1446     // FIXME: This should be possible on generated content but is not right now.
1447     if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node())
1448         return;
1449 
1450     // Set the width and height of the shadow ancestor node if there is one.
1451     // This is necessary for textarea elements since the resizable layer is in the shadow content.
1452     Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode());
1453     RenderBox* renderer = toRenderBox(element->renderer());
1454 
1455     EResize resize = renderer->style()->resize();
1456     if (resize == RESIZE_NONE)
1457         return;
1458 
1459     Document* document = element->document();
1460     if (!document->frame()->eventHandler()->mousePressed())
1461         return;
1462 
1463     float zoomFactor = renderer->style()->effectiveZoom();
1464 
1465     IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos()));
1466     newOffset.setWidth(newOffset.width() / zoomFactor);
1467     newOffset.setHeight(newOffset.height() / zoomFactor);
1468 
1469     IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);
1470     IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
1471     element->setMinimumSizeForResizing(minimumSize);
1472 
1473     IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
1474 
1475     IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
1476 
1477     CSSStyleDeclaration* style = element->style();
1478     bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
1479 
1480     ExceptionCode ec;
1481 
1482     if (resize != RESIZE_VERTICAL && difference.width()) {
1483         if (element->isFormControlElement()) {
1484             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1485             style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);
1486             style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec);
1487         }
1488         int baseWidth = renderer->width() - (isBoxSizingBorder ? 0
1489             : renderer->borderLeft() + renderer->paddingLeft() + renderer->borderRight() + renderer->paddingRight());
1490         baseWidth = baseWidth / zoomFactor;
1491         style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);
1492     }
1493 
1494     if (resize != RESIZE_HORIZONTAL && difference.height()) {
1495         if (element->isFormControlElement()) {
1496             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1497             style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);
1498             style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec);
1499         }
1500         int baseHeight = renderer->height() - (isBoxSizingBorder ? 0
1501             : renderer->borderTop() + renderer->paddingTop() + renderer->borderBottom() + renderer->paddingBottom());
1502         baseHeight = baseHeight / zoomFactor;
1503         style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec);
1504     }
1505 
1506     document->updateLayout();
1507 
1508     // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
1509 }
1510 
valueChanged(Scrollbar *)1511 void RenderLayer::valueChanged(Scrollbar*)
1512 {
1513     // Update scroll position from scrollbars.
1514 
1515     bool needUpdate = false;
1516     int newX = scrollXOffset();
1517     int newY = m_scrollY;
1518 
1519     if (m_hBar) {
1520         newX = m_hBar->value();
1521         if (newX != scrollXOffset())
1522            needUpdate = true;
1523     }
1524 
1525     if (m_vBar) {
1526         newY = m_vBar->value();
1527         if (newY != m_scrollY)
1528            needUpdate = true;
1529     }
1530 
1531     if (needUpdate)
1532         scrollToOffset(newX, newY, false);
1533 }
1534 
isActive() const1535 bool RenderLayer::isActive() const
1536 {
1537     Page* page = renderer()->document()->frame()->page();
1538     return page && page->focusController()->isActive();
1539 }
1540 
1541 
cornerRect(const RenderLayer * layer,const IntRect & bounds)1542 static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds)
1543 {
1544     int horizontalThickness;
1545     int verticalThickness;
1546     if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1547         // FIXME: This isn't right.  We need to know the thickness of custom scrollbars
1548         // even when they don't exist in order to set the resizer square size properly.
1549         horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
1550         verticalThickness = horizontalThickness;
1551     } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1552         horizontalThickness = layer->verticalScrollbar()->width();
1553         verticalThickness = horizontalThickness;
1554     } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) {
1555         verticalThickness = layer->horizontalScrollbar()->height();
1556         horizontalThickness = verticalThickness;
1557     } else {
1558         horizontalThickness = layer->verticalScrollbar()->width();
1559         verticalThickness = layer->horizontalScrollbar()->height();
1560     }
1561     return IntRect(bounds.right() - horizontalThickness - layer->renderer()->style()->borderRightWidth(),
1562                    bounds.bottom() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),
1563                    horizontalThickness, verticalThickness);
1564 }
1565 
scrollCornerRect(const RenderLayer * layer,const IntRect & bounds)1566 static IntRect scrollCornerRect(const RenderLayer* layer, const IntRect& bounds)
1567 {
1568     // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
1569     // This happens when:
1570     // (a) A resizer is present and at least one scrollbar is present
1571     // (b) Both scrollbars are present.
1572     bool hasHorizontalBar = layer->horizontalScrollbar();
1573     bool hasVerticalBar = layer->verticalScrollbar();
1574     bool hasResizer = layer->renderer()->style()->resize() != RESIZE_NONE;
1575     if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
1576         return cornerRect(layer, bounds);
1577     return IntRect();
1578 }
1579 
resizerCornerRect(const RenderLayer * layer,const IntRect & bounds)1580 static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
1581 {
1582     ASSERT(layer->renderer()->isBox());
1583     if (layer->renderer()->style()->resize() == RESIZE_NONE)
1584         return IntRect();
1585     return cornerRect(layer, bounds);
1586 }
1587 
scrollbarCornerPresent() const1588 bool RenderLayer::scrollbarCornerPresent() const
1589 {
1590     ASSERT(renderer()->isBox());
1591     return !scrollCornerRect(this, renderBox()->borderBoxRect()).isEmpty();
1592 }
1593 
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntRect & scrollbarRect) const1594 IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
1595 {
1596     RenderView* view = renderer()->view();
1597     if (!view)
1598         return scrollbarRect;
1599 
1600     IntRect rect = scrollbarRect;
1601     rect.move(scrollbarOffset(scrollbar));
1602 
1603     return view->frameView()->convertFromRenderer(renderer(), rect);
1604 }
1605 
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntRect & parentRect) const1606 IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
1607 {
1608     RenderView* view = renderer()->view();
1609     if (!view)
1610         return parentRect;
1611 
1612     IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect);
1613     rect.move(-scrollbarOffset(scrollbar));
1614     return rect;
1615 }
1616 
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntPoint & scrollbarPoint) const1617 IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
1618 {
1619     RenderView* view = renderer()->view();
1620     if (!view)
1621         return scrollbarPoint;
1622 
1623     IntPoint point = scrollbarPoint;
1624     point.move(scrollbarOffset(scrollbar));
1625     return view->frameView()->convertFromRenderer(renderer(), point);
1626 }
1627 
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntPoint & parentPoint) const1628 IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
1629 {
1630     RenderView* view = renderer()->view();
1631     if (!view)
1632         return parentPoint;
1633 
1634     IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint);
1635 
1636     point.move(-scrollbarOffset(scrollbar));
1637     return point;
1638 }
1639 
scrollbarOffset(const Scrollbar * scrollbar) const1640 IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
1641 {
1642     RenderBox* box = renderBox();
1643 
1644     if (scrollbar == m_vBar.get())
1645         return IntSize(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
1646 
1647     if (scrollbar == m_hBar.get())
1648         return IntSize(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
1649 
1650     ASSERT_NOT_REACHED();
1651     return IntSize();
1652 }
1653 
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)1654 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1655 {
1656     IntRect scrollRect = rect;
1657     RenderBox* box = renderBox();
1658     ASSERT(box);
1659     if (scrollbar == m_vBar.get())
1660         scrollRect.move(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
1661     else
1662         scrollRect.move(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
1663     renderer()->repaintRectangle(scrollRect);
1664 }
1665 
createScrollbar(ScrollbarOrientation orientation)1666 PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
1667 {
1668     RefPtr<Scrollbar> widget;
1669     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
1670     bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);
1671     if (hasCustomScrollbarStyle)
1672         widget = RenderScrollbar::createCustomScrollbar(this, orientation, toRenderBox(actualRenderer));
1673     else
1674         widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
1675     renderer()->document()->view()->addChild(widget.get());
1676     return widget.release();
1677 }
1678 
destroyScrollbar(ScrollbarOrientation orientation)1679 void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
1680 {
1681     RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
1682     if (scrollbar) {
1683         scrollbar->removeFromParent();
1684         scrollbar->setClient(0);
1685         scrollbar = 0;
1686     }
1687 }
1688 
setHasHorizontalScrollbar(bool hasScrollbar)1689 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
1690 {
1691     if (hasScrollbar == (m_hBar != 0))
1692         return;
1693 
1694     if (hasScrollbar)
1695         m_hBar = createScrollbar(HorizontalScrollbar);
1696     else
1697         destroyScrollbar(HorizontalScrollbar);
1698 
1699     // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1700     if (m_hBar)
1701         m_hBar->styleChanged();
1702     if (m_vBar)
1703         m_vBar->styleChanged();
1704 
1705 #if ENABLE(DASHBOARD_SUPPORT)
1706     // Force an update since we know the scrollbars have changed things.
1707     if (renderer()->document()->hasDashboardRegions())
1708         renderer()->document()->setDashboardRegionsDirty(true);
1709 #endif
1710 }
1711 
setHasVerticalScrollbar(bool hasScrollbar)1712 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
1713 {
1714     if (hasScrollbar == (m_vBar != 0))
1715         return;
1716 
1717     if (hasScrollbar)
1718         m_vBar = createScrollbar(VerticalScrollbar);
1719     else
1720         destroyScrollbar(VerticalScrollbar);
1721 
1722      // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1723     if (m_hBar)
1724         m_hBar->styleChanged();
1725     if (m_vBar)
1726         m_vBar->styleChanged();
1727 
1728 #if ENABLE(DASHBOARD_SUPPORT)
1729     // Force an update since we know the scrollbars have changed things.
1730     if (renderer()->document()->hasDashboardRegions())
1731         renderer()->document()->setDashboardRegionsDirty(true);
1732 #endif
1733 }
1734 
verticalScrollbarWidth() const1735 int RenderLayer::verticalScrollbarWidth() const
1736 {
1737     if (!m_vBar)
1738         return 0;
1739     return m_vBar->width();
1740 }
1741 
horizontalScrollbarHeight() const1742 int RenderLayer::horizontalScrollbarHeight() const
1743 {
1744     if (!m_hBar)
1745         return 0;
1746     return m_hBar->height();
1747 }
1748 
offsetFromResizeCorner(const IntPoint & absolutePoint) const1749 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
1750 {
1751     // Currently the resize corner is always the bottom right corner
1752     IntPoint bottomRight(width(), height());
1753     IntPoint localPoint = absoluteToContents(absolutePoint);
1754     return localPoint - bottomRight;
1755 }
1756 
hasOverflowControls() const1757 bool RenderLayer::hasOverflowControls() const
1758 {
1759     return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE;
1760 }
1761 
positionOverflowControls(int tx,int ty)1762 void RenderLayer::positionOverflowControls(int tx, int ty)
1763 {
1764     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
1765         return;
1766 
1767     RenderBox* box = renderBox();
1768     if (!box)
1769         return;
1770 
1771     IntRect borderBox = box->borderBoxRect();
1772     IntRect scrollCorner(scrollCornerRect(this, borderBox));
1773     IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
1774     if (m_vBar)
1775         m_vBar->setFrameRect(IntRect(absBounds.right() - box->borderRight() - m_vBar->width(),
1776                                      absBounds.y() + box->borderTop(),
1777                                      m_vBar->width(),
1778                                      absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height()));
1779 
1780     if (m_hBar)
1781         m_hBar->setFrameRect(IntRect(absBounds.x() + box->borderLeft(),
1782                                      absBounds.bottom() - box->borderBottom() - m_hBar->height(),
1783                                      absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
1784                                      m_hBar->height()));
1785 
1786     if (m_scrollCorner)
1787         m_scrollCorner->setFrameRect(scrollCorner);
1788     if (m_resizer)
1789         m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
1790 }
1791 
scrollWidth()1792 int RenderLayer::scrollWidth()
1793 {
1794     if (m_scrollDimensionsDirty)
1795         computeScrollDimensions();
1796     return m_scrollWidth;
1797 }
1798 
scrollHeight()1799 int RenderLayer::scrollHeight()
1800 {
1801     if (m_scrollDimensionsDirty)
1802         computeScrollDimensions();
1803     return m_scrollHeight;
1804 }
1805 
computeScrollDimensions(bool * needHBar,bool * needVBar)1806 void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
1807 {
1808     RenderBox* box = renderBox();
1809     ASSERT(box);
1810 
1811     m_scrollDimensionsDirty = false;
1812 
1813     bool ltr = renderer()->style()->direction() == LTR;
1814 
1815     int clientWidth = box->clientWidth();
1816     int clientHeight = box->clientHeight();
1817 
1818     m_scrollLeftOverflow = ltr ? 0 : min(0, box->leftmostPosition(true, false) - box->borderLeft());
1819 
1820     int rightPos = ltr ?
1821                     box->rightmostPosition(true, false) - box->borderLeft() :
1822                     clientWidth - m_scrollLeftOverflow;
1823     int bottomPos = box->lowestPosition(true, false) - box->borderTop();
1824 
1825     m_scrollWidth = max(rightPos, clientWidth);
1826     m_scrollHeight = max(bottomPos, clientHeight);
1827 
1828     m_scrollOriginX = ltr ? 0 : m_scrollWidth - clientWidth;
1829 
1830     if (needHBar)
1831         *needHBar = rightPos > clientWidth;
1832     if (needVBar)
1833         *needVBar = bottomPos > clientHeight;
1834 }
1835 
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)1836 void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
1837 {
1838     if (m_overflowStatusDirty) {
1839         m_horizontalOverflow = horizontalOverflow;
1840         m_verticalOverflow = verticalOverflow;
1841         m_overflowStatusDirty = false;
1842 
1843         return;
1844     }
1845 
1846     bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
1847     bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
1848 
1849     if (horizontalOverflowChanged || verticalOverflowChanged) {
1850         m_horizontalOverflow = horizontalOverflow;
1851         m_verticalOverflow = verticalOverflow;
1852 
1853         if (FrameView* frameView = renderer()->document()->view()) {
1854             frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
1855                 renderer()->node());
1856         }
1857     }
1858 }
1859 
1860 void
updateScrollInfoAfterLayout()1861 RenderLayer::updateScrollInfoAfterLayout()
1862 {
1863     RenderBox* box = renderBox();
1864     if (!box)
1865         return;
1866 
1867     m_scrollDimensionsDirty = true;
1868 
1869     bool horizontalOverflow, verticalOverflow;
1870     computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
1871 
1872     if (box->style()->overflowX() != OMARQUEE) {
1873         // Layout may cause us to be in an invalid scroll position.  In this case we need
1874         // to pull our scroll offsets back to the max (or push them up to the min).
1875         int newX = max(0, min(scrollXOffset(), scrollWidth() - box->clientWidth()));
1876         int newY = max(0, min(m_scrollY, scrollHeight() - box->clientHeight()));
1877         if (newX != scrollXOffset() || newY != m_scrollY) {
1878             RenderView* view = renderer()->view();
1879             ASSERT(view);
1880             // scrollToOffset() may call updateLayerPositions(), which doesn't work
1881             // with LayoutState.
1882             // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes.
1883             if (view)
1884                 view->disableLayoutState();
1885             scrollToOffset(newX, newY);
1886             if (view)
1887                 view->enableLayoutState();
1888         }
1889     }
1890 
1891     bool haveHorizontalBar = m_hBar;
1892     bool haveVerticalBar = m_vBar;
1893 
1894     // overflow:scroll should just enable/disable.
1895     if (renderer()->style()->overflowX() == OSCROLL)
1896         m_hBar->setEnabled(horizontalOverflow);
1897     if (renderer()->style()->overflowY() == OSCROLL)
1898         m_vBar->setEnabled(verticalOverflow);
1899 
1900     // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
1901     // scrollbars that may be present.
1902     if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar)
1903         setHasHorizontalScrollbar(false);
1904     if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar)
1905         setHasVerticalScrollbar(false);
1906 
1907     // overflow:auto may need to lay out again if scrollbars got added/removed.
1908     bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
1909                              (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
1910     if (scrollbarsChanged) {
1911         if (box->hasAutoHorizontalScrollbar())
1912             setHasHorizontalScrollbar(horizontalOverflow);
1913         if (box->hasAutoVerticalScrollbar())
1914             setHasVerticalScrollbar(verticalOverflow);
1915 
1916 #if ENABLE(DASHBOARD_SUPPORT)
1917         // Force an update since we know the scrollbars have changed things.
1918         if (renderer()->document()->hasDashboardRegions())
1919             renderer()->document()->setDashboardRegionsDirty(true);
1920 #endif
1921 
1922         renderer()->repaint();
1923 
1924         if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) {
1925             if (!m_inOverflowRelayout) {
1926                 // Our proprietary overflow: overlay value doesn't trigger a layout.
1927                 m_inOverflowRelayout = true;
1928                 renderer()->setNeedsLayout(true, false);
1929                 if (renderer()->isRenderBlock())
1930                     toRenderBlock(renderer())->layoutBlock(true);
1931                 else
1932                     renderer()->layout();
1933                 m_inOverflowRelayout = false;
1934             }
1935         }
1936     }
1937 
1938     // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
1939     if (m_hBar && box->hasAutoHorizontalScrollbar())
1940         m_hBar->setEnabled(true);
1941     if (m_vBar && box->hasAutoVerticalScrollbar())
1942         m_vBar->setEnabled(true);
1943 
1944     // Set up the range (and page step/line step).
1945     if (m_hBar) {
1946         int clientWidth = box->clientWidth();
1947         int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
1948         m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
1949         m_hBar->setProportion(clientWidth, m_scrollWidth);
1950         // Explicitly set the horizontal scroll value.  This ensures that when a
1951         // right-to-left scrollable area's width (or content width) changes, the
1952         // top right corner of the content doesn't shift with respect to the top
1953         // right corner of the area. Conceptually, right-to-left areas have
1954         // their origin at the top-right, but RenderLayer is top-left oriented,
1955         // so this is needed to keep everything working (see how scrollXOffset()
1956         // differs from scrollYOffset() to get an idea of why the horizontal and
1957         // vertical scrollbars need to be treated differently).
1958         m_hBar->setValue(scrollXOffset());
1959     }
1960     if (m_vBar) {
1961         int clientHeight = box->clientHeight();
1962         int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
1963         m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
1964         m_vBar->setProportion(clientHeight, m_scrollHeight);
1965     }
1966 
1967     if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
1968         updateOverflowStatus(horizontalOverflow, verticalOverflow);
1969 }
1970 
paintOverflowControls(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)1971 void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
1972 {
1973     // Don't do anything if we have no overflow.
1974     if (!renderer()->hasOverflowClip())
1975         return;
1976 
1977     // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes
1978     // widgets can move without layout occurring (most notably when you scroll a document that
1979     // contains fixed positioned elements).
1980     positionOverflowControls(tx, ty);
1981 
1982     // Now that we're sure the scrollbars are in the right place, paint them.
1983     if (m_hBar)
1984         m_hBar->paint(context, damageRect);
1985     if (m_vBar)
1986         m_vBar->paint(context, damageRect);
1987 
1988     // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
1989     // edge of the box.
1990     paintScrollCorner(context, tx, ty, damageRect);
1991 
1992     // Paint our resizer last, since it sits on top of the scroll corner.
1993     paintResizer(context, tx, ty, damageRect);
1994 }
1995 
paintScrollCorner(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)1996 void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
1997 {
1998     RenderBox* box = renderBox();
1999     ASSERT(box);
2000 
2001     IntRect cornerRect = scrollCornerRect(this, box->borderBoxRect());
2002     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
2003     if (!absRect.intersects(damageRect))
2004         return;
2005 
2006     if (context->updatingControlTints()) {
2007         updateScrollCornerStyle();
2008         return;
2009     }
2010 
2011     if (m_scrollCorner) {
2012         m_scrollCorner->paintIntoRect(context, tx, ty, absRect);
2013         return;
2014     }
2015 
2016     context->fillRect(absRect, Color::white, box->style()->colorSpace());
2017 }
2018 
paintResizer(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)2019 void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
2020 {
2021     if (renderer()->style()->resize() == RESIZE_NONE)
2022         return;
2023 
2024     RenderBox* box = renderBox();
2025     ASSERT(box);
2026 
2027     IntRect cornerRect = resizerCornerRect(this, box->borderBoxRect());
2028     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
2029     if (!absRect.intersects(damageRect))
2030         return;
2031 
2032     if (context->updatingControlTints()) {
2033         updateResizerStyle();
2034         return;
2035     }
2036 
2037     if (m_resizer) {
2038         m_resizer->paintIntoRect(context, tx, ty, absRect);
2039         return;
2040     }
2041 
2042     // Paint the resizer control.
2043     DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner")));
2044     IntPoint imagePoint(absRect.right() - resizeCornerImage->width(), absRect.bottom() - resizeCornerImage->height());
2045     context->drawImage(resizeCornerImage.get(), box->style()->colorSpace(), imagePoint);
2046 
2047     // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
2048     // Clipping will exclude the right and bottom edges of this frame.
2049     if (m_hBar || m_vBar) {
2050         context->save();
2051         context->clip(absRect);
2052         IntRect largerCorner = absRect;
2053         largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
2054         context->setStrokeColor(Color(makeRGB(217, 217, 217)), DeviceColorSpace);
2055         context->setStrokeThickness(1.0f);
2056         context->setFillColor(Color::transparent, DeviceColorSpace);
2057         context->drawRect(largerCorner);
2058         context->restore();
2059     }
2060 }
2061 
isPointInResizeControl(const IntPoint & absolutePoint) const2062 bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
2063 {
2064     if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)
2065         return false;
2066 
2067     RenderBox* box = renderBox();
2068     ASSERT(box);
2069 
2070     IntPoint localPoint = absoluteToContents(absolutePoint);
2071 
2072     IntRect localBounds(0, 0, box->width(), box->height());
2073     return resizerCornerRect(this, localBounds).contains(localPoint);
2074 }
2075 
hitTestOverflowControls(HitTestResult & result,const IntPoint & localPoint)2076 bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
2077 {
2078     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
2079         return false;
2080 
2081     RenderBox* box = renderBox();
2082     ASSERT(box);
2083 
2084     IntRect resizeControlRect;
2085     if (renderer()->style()->resize() != RESIZE_NONE) {
2086         resizeControlRect = resizerCornerRect(this, box->borderBoxRect());
2087         if (resizeControlRect.contains(localPoint))
2088             return true;
2089     }
2090 
2091     int resizeControlSize = max(resizeControlRect.height(), 0);
2092 
2093     if (m_vBar) {
2094         IntRect vBarRect(box->width() - box->borderRight() - m_vBar->width(),
2095                          box->borderTop(),
2096                          m_vBar->width(),
2097                          box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
2098         if (vBarRect.contains(localPoint)) {
2099             result.setScrollbar(m_vBar.get());
2100             return true;
2101         }
2102     }
2103 
2104     resizeControlSize = max(resizeControlRect.width(), 0);
2105     if (m_hBar) {
2106         IntRect hBarRect(box->borderLeft(),
2107                          box->height() - box->borderBottom() - m_hBar->height(),
2108                          box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
2109                          m_hBar->height());
2110         if (hBarRect.contains(localPoint)) {
2111             result.setScrollbar(m_hBar.get());
2112             return true;
2113         }
2114     }
2115 
2116     return false;
2117 }
2118 
scroll(ScrollDirection direction,ScrollGranularity granularity,float multiplier)2119 bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
2120 {
2121     bool didHorizontalScroll = false;
2122     bool didVerticalScroll = false;
2123 
2124     if (m_hBar) {
2125         if (granularity == ScrollByDocument) {
2126             // Special-case for the ScrollByDocument granularity. A document scroll can only be up
2127             // or down and in both cases the horizontal bar goes all the way to the left.
2128             didHorizontalScroll = m_hBar->scroll(ScrollLeft, ScrollByDocument, multiplier);
2129         } else
2130             didHorizontalScroll = m_hBar->scroll(direction, granularity, multiplier);
2131     }
2132 
2133     if (m_vBar)
2134         didVerticalScroll = m_vBar->scroll(direction, granularity, multiplier);
2135 
2136     return (didHorizontalScroll || didVerticalScroll);
2137 }
2138 
paint(GraphicsContext * p,const IntRect & damageRect,PaintBehavior paintBehavior,RenderObject * paintingRoot)2139 void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot)
2140 {
2141     RenderObject::OverlapTestRequestMap overlapTestRequests;
2142     paintLayer(this, p, damageRect, paintBehavior, paintingRoot, &overlapTestRequests);
2143     RenderObject::OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2144     for (RenderObject::OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
2145         it->first->setOverlapTestResult(false);
2146 }
2147 
setClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)2148 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
2149 {
2150     if (paintDirtyRect == clipRect)
2151         return;
2152     p->save();
2153     p->clip(clipRect);
2154 }
2155 
restoreClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)2156 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
2157 {
2158     if (paintDirtyRect == clipRect)
2159         return;
2160     p->restore();
2161 }
2162 
performOverlapTests(RenderObject::OverlapTestRequestMap & overlapTestRequests,const IntRect & layerBounds)2163 static void performOverlapTests(RenderObject::OverlapTestRequestMap& overlapTestRequests, const IntRect& layerBounds)
2164 {
2165     Vector<OverlapTestRequestClient*> overlappedRequestClients;
2166     RenderObject::OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2167     for (RenderObject::OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
2168         if (!layerBounds.intersects(it->second))
2169             continue;
2170 
2171         it->first->setOverlapTestResult(true);
2172         overlappedRequestClients.append(it->first);
2173     }
2174     for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
2175         overlapTestRequests.remove(overlappedRequestClients[i]);
2176 }
2177 
2178 #if USE(ACCELERATED_COMPOSITING)
shouldDoSoftwarePaint(const RenderLayer * layer,bool paintingReflection)2179 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
2180 {
2181     return paintingReflection && !layer->has3DTransform();
2182 }
2183 #endif
2184 
paintLayer(RenderLayer * rootLayer,GraphicsContext * p,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,RenderObject::OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags)2185 void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
2186                         const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2187                         RenderObject* paintingRoot, RenderObject::OverlapTestRequestMap* overlapTestRequests,
2188                         PaintLayerFlags paintFlags)
2189 {
2190 #if USE(ACCELERATED_COMPOSITING)
2191     if (isComposited()) {
2192         // The updatingControlTints() painting pass goes through compositing layers,
2193         // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
2194         if (p->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers))
2195             paintFlags |= PaintLayerTemporaryClipRects;
2196         else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
2197             // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
2198             return;
2199         }
2200     }
2201 #endif
2202 
2203     // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
2204     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
2205     // will do a full repaint().
2206     if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
2207         return;
2208 
2209     // If this layer is totally invisible then there is nothing to paint.
2210     if (!renderer()->opacity())
2211         return;
2212 
2213     if (paintsWithTransparency(paintBehavior))
2214         paintFlags |= PaintLayerHaveTransparency;
2215 
2216     // Apply a transform if we have one.  A reflection is considered to be a transform, since it is a flip and a translate.
2217     if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
2218         TransformationMatrix layerTransform = renderableTransform(paintBehavior);
2219         // If the transform can't be inverted, then don't paint anything.
2220         if (!layerTransform.isInvertible())
2221             return;
2222 
2223         // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
2224         // layer from the parent now.
2225         if (paintFlags & PaintLayerHaveTransparency)
2226             parent()->beginTransparencyLayers(p, rootLayer, paintBehavior);
2227 
2228         // Make sure the parent's clip rects have been calculated.
2229         IntRect clipRect = paintDirtyRect;
2230         if (parent()) {
2231             clipRect = backgroundClipRect(rootLayer, paintFlags & PaintLayerTemporaryClipRects);
2232             clipRect.intersect(paintDirtyRect);
2233         }
2234 
2235         // Push the parent coordinate space's clip.
2236         setClip(p, paintDirtyRect, clipRect);
2237 
2238         // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
2239         // This involves subtracting out the position of the layer in our current coordinate space.
2240         int x = 0;
2241         int y = 0;
2242         convertToLayerCoords(rootLayer, x, y);
2243         TransformationMatrix transform(layerTransform);
2244         transform.translateRight(x, y);
2245 
2246         // Apply the transform.
2247         p->save();
2248         p->concatCTM(transform.toAffineTransform());
2249 
2250         // Now do a paint with the root layer shifted to be us.
2251         paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform);
2252 
2253         p->restore();
2254 
2255         // Restore the clip.
2256         restoreClip(p, paintDirtyRect, clipRect);
2257 
2258         return;
2259     }
2260 
2261     PaintLayerFlags localPaintFlags = paintFlags & ~PaintLayerAppliedTransform;
2262     bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency;
2263 
2264     // Paint the reflection first if we have one.
2265     if (m_reflection && !m_paintingInsideReflection) {
2266         // Mark that we are now inside replica painting.
2267         m_paintingInsideReflection = true;
2268         reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection);
2269         m_paintingInsideReflection = false;
2270     }
2271 
2272     // Calculate the clip rects we should use.
2273     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
2274     calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects);
2275     int x = layerBounds.x();
2276     int y = layerBounds.y();
2277     int tx = x - renderBoxX();
2278     int ty = y - renderBoxY();
2279 
2280     // Ensure our lists are up-to-date.
2281     updateCompositingAndLayerListsIfNeeded();
2282 
2283     bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
2284     bool selectionOnly  = paintBehavior & PaintBehaviorSelectionOnly;
2285 
2286     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
2287     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
2288     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
2289     // so it will be tested against as we descend through the renderers.
2290     RenderObject* paintingRootForRenderer = 0;
2291     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
2292         paintingRootForRenderer = paintingRoot;
2293 
2294     if (overlapTestRequests)
2295         performOverlapTests(*overlapTestRequests, layerBounds);
2296 
2297     // We want to paint our layer, but only if we intersect the damage rect.
2298     bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent && isSelfPaintingLayer();
2299     if (shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
2300         // Begin transparency layers lazily now that we know we have to paint something.
2301         if (haveTransparency)
2302             beginTransparencyLayers(p, rootLayer, paintBehavior);
2303 
2304         // Paint our background first, before painting any child layers.
2305         // Establish the clip used to paint our background.
2306         setClip(p, paintDirtyRect, damageRect);
2307 
2308         // Paint the background.
2309         RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
2310         renderer()->paint(paintInfo, tx, ty);
2311 
2312         // Restore the clip.
2313         restoreClip(p, paintDirtyRect, damageRect);
2314     }
2315 
2316     // Now walk the sorted list of children with negative z-indices.
2317     if (m_negZOrderList)
2318         for (Vector<RenderLayer*>::iterator it = m_negZOrderList->begin(); it != m_negZOrderList->end(); ++it)
2319             it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2320 
2321     // Now establish the appropriate clip and paint our child RenderObjects.
2322     if (shouldPaint && !clipRectToApply.isEmpty()) {
2323         // Begin transparency layers lazily now that we know we have to paint something.
2324         if (haveTransparency)
2325             beginTransparencyLayers(p, rootLayer, paintBehavior);
2326 
2327         // Set up the clip used when painting our children.
2328         setClip(p, paintDirtyRect, clipRectToApply);
2329         RenderObject::PaintInfo paintInfo(p, clipRectToApply,
2330                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
2331                                           forceBlackText, paintingRootForRenderer, 0);
2332         renderer()->paint(paintInfo, tx, ty);
2333         if (!selectionOnly) {
2334             paintInfo.phase = PaintPhaseFloat;
2335             renderer()->paint(paintInfo, tx, ty);
2336             paintInfo.phase = PaintPhaseForeground;
2337             paintInfo.overlapTestRequests = overlapTestRequests;
2338             renderer()->paint(paintInfo, tx, ty);
2339             paintInfo.phase = PaintPhaseChildOutlines;
2340             renderer()->paint(paintInfo, tx, ty);
2341         }
2342 
2343         // Now restore our clip.
2344         restoreClip(p, paintDirtyRect, clipRectToApply);
2345     }
2346 
2347     if (!outlineRect.isEmpty() && isSelfPaintingLayer()) {
2348         // Paint our own outline
2349         RenderObject::PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
2350         setClip(p, paintDirtyRect, outlineRect);
2351         renderer()->paint(paintInfo, tx, ty);
2352         restoreClip(p, paintDirtyRect, outlineRect);
2353     }
2354 
2355     // Paint any child layers that have overflow.
2356     if (m_normalFlowList)
2357         for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it)
2358             it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2359 
2360     // Now walk the sorted list of children with positive z-indices.
2361     if (m_posZOrderList)
2362         for (Vector<RenderLayer*>::iterator it = m_posZOrderList->begin(); it != m_posZOrderList->end(); ++it)
2363             it[0]->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2364 
2365     if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty()) {
2366         setClip(p, paintDirtyRect, damageRect);
2367 
2368         // Paint the mask.
2369         RenderObject::PaintInfo paintInfo(p, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
2370         renderer()->paint(paintInfo, tx, ty);
2371 
2372         // Restore the clip.
2373         restoreClip(p, paintDirtyRect, damageRect);
2374     }
2375 
2376     // End our transparency layer
2377     if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
2378         p->endTransparencyLayer();
2379         p->restore();
2380         m_usedTransparency = false;
2381     }
2382 }
2383 
frameVisibleRect(RenderObject * renderer)2384 static inline IntRect frameVisibleRect(RenderObject* renderer)
2385 {
2386     FrameView* frameView = renderer->document()->view();
2387     if (!frameView)
2388         return IntRect();
2389 
2390     return frameView->visibleContentRect();
2391 }
2392 
hitTest(const HitTestRequest & request,HitTestResult & result)2393 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
2394 {
2395     renderer()->document()->updateLayout();
2396 
2397     IntRect boundsRect(m_x, m_y, width(), height());
2398     if (!request.ignoreClipping())
2399         boundsRect.intersect(frameVisibleRect(renderer()));
2400 
2401     RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, boundsRect, result.point(), false);
2402     if (!insideLayer) {
2403         // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
2404         // return ourselves. We do this so mouse events continue getting delivered after a drag has
2405         // exited the WebView, and so hit testing over a scrollbar hits the content document.
2406         if ((request.active() || request.mouseUp()) && renderer()->isRenderView()) {
2407             renderer()->updateHitTestResult(result, result.point());
2408             insideLayer = this;
2409         }
2410     }
2411 
2412     // Now determine if the result is inside an anchor - if the urlElement isn't already set.
2413     Node* node = result.innerNode();
2414     if (node && !result.URLElement())
2415         result.setURLElement(static_cast<Element*>(node->enclosingLinkEventParentOrSelf()));
2416 
2417     // Next set up the correct :hover/:active state along the new chain.
2418     updateHoverActiveState(request, result);
2419 
2420     // Now return whether we were inside this layer (this will always be true for the root
2421     // layer).
2422     return insideLayer;
2423 }
2424 
enclosingElement() const2425 Node* RenderLayer::enclosingElement() const
2426 {
2427     for (RenderObject* r = renderer(); r; r = r->parent()) {
2428         if (Node* e = r->node())
2429             return e;
2430     }
2431     ASSERT_NOT_REACHED();
2432     return 0;
2433 }
2434 
2435 // Compute the z-offset of the point in the transformState.
2436 // This is effectively projecting a ray normal to the plane of ancestor, finding where that
2437 // ray intersects target, and computing the z delta between those two points.
computeZOffset(const HitTestingTransformState & transformState)2438 static double computeZOffset(const HitTestingTransformState& transformState)
2439 {
2440     // We got an affine transform, so no z-offset
2441     if (transformState.m_accumulatedTransform.isAffine())
2442         return 0;
2443 
2444     // Flatten the point into the target plane
2445     FloatPoint targetPoint = transformState.mappedPoint();
2446 
2447     // Now map the point back through the transform, which computes Z.
2448     FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
2449     return backmappedPoint.z();
2450 }
2451 
createLocalTransformState(RenderLayer * rootLayer,RenderLayer * containerLayer,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * containerTransformState) const2452 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
2453                                         const IntRect& hitTestRect, const IntPoint& hitTestPoint,
2454                                         const HitTestingTransformState* containerTransformState) const
2455 {
2456     RefPtr<HitTestingTransformState> transformState;
2457     int offsetX = 0;
2458     int offsetY = 0;
2459     if (containerTransformState) {
2460         // If we're already computing transform state, then it's relative to the container (which we know is non-null).
2461         transformState = HitTestingTransformState::create(*containerTransformState);
2462         convertToLayerCoords(containerLayer, offsetX, offsetY);
2463     } else {
2464         // If this is the first time we need to make transform state, then base it off of hitTestPoint,
2465         // which is relative to rootLayer.
2466         transformState = HitTestingTransformState::create(hitTestPoint, FloatQuad(hitTestRect));
2467         convertToLayerCoords(rootLayer, offsetX, offsetY);
2468     }
2469 
2470     RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
2471     if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
2472         TransformationMatrix containerTransform;
2473         renderer()->getTransformFromContainer(containerRenderer, IntSize(offsetX, offsetY), containerTransform);
2474         transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
2475     } else {
2476         transformState->translate(offsetX, offsetY, HitTestingTransformState::AccumulateTransform);
2477     }
2478 
2479     return transformState;
2480 }
2481 
2482 
isHitCandidate(const RenderLayer * hitLayer,bool canDepthSort,double * zOffset,const HitTestingTransformState * transformState)2483 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
2484 {
2485     if (!hitLayer)
2486         return false;
2487 
2488     // The hit layer is depth-sorting with other layers, so just say that it was hit.
2489     if (canDepthSort)
2490         return true;
2491 
2492     // We need to look at z-depth to decide if this layer was hit.
2493     if (zOffset) {
2494         ASSERT(transformState);
2495         // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
2496         double childZOffset = computeZOffset(*transformState);
2497         if (childZOffset > *zOffset) {
2498             *zOffset = childZOffset;
2499             return true;
2500         }
2501         return false;
2502     }
2503 
2504     return true;
2505 }
2506 
2507 // hitTestPoint and hitTestRect are relative to rootLayer.
2508 // A 'flattening' layer is one preserves3D() == false.
2509 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
2510 // transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer.
2511 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
2512 //
2513 // If zOffset is non-null (which indicates that the caller wants z offset information),
2514 //  *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
hitTestLayer(RenderLayer * rootLayer,RenderLayer * containerLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,bool appliedTransform,const HitTestingTransformState * transformState,double * zOffset)2515 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
2516                                                 const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
2517                                                 const HitTestingTransformState* transformState, double* zOffset)
2518 {
2519     // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
2520 
2521     bool useTemporaryClipRects = false;
2522 #if USE(ACCELERATED_COMPOSITING)
2523     useTemporaryClipRects = compositor()->inCompositingMode();
2524 #endif
2525 
2526     // Apply a transform if we have one.
2527     if (transform() && !appliedTransform) {
2528         // Make sure the parent's clip rects have been calculated.
2529         if (parent()) {
2530             IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects);
2531             // Go ahead and test the enclosing clip now.
2532             if (!clipRect.contains(hitTestPoint))
2533                 return 0;
2534         }
2535 
2536         // Create a transform state to accumulate this transform.
2537         RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
2538 
2539         // If the transform can't be inverted, then don't hit test this layer at all.
2540         if (!newTransformState->m_accumulatedTransform.isInvertible())
2541             return 0;
2542 
2543         // Compute the point and the hit test rect in the coords of this layer by using the values
2544         // from the transformState, which store the point and quad in the coords of the last flattened
2545         // layer, and the accumulated transform which lets up map through preserve-3d layers.
2546         //
2547         // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z)
2548         // by our container.
2549         IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
2550         IntRect localHitTestRect;
2551 #if USE(ACCELERATED_COMPOSITING)
2552         if (isComposited()) {
2553             // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting.
2554             localHitTestRect = backing()->compositedBounds();
2555         } else
2556 #endif
2557             localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
2558 
2559         // Now do a hit test with the root layer shifted to be us.
2560         return hitTestLayer(this, containerLayer, request, result, localHitTestRect, localPoint, true, newTransformState.get(), zOffset);
2561     }
2562 
2563     // Ensure our lists and 3d status are up-to-date.
2564     updateCompositingAndLayerListsIfNeeded();
2565     update3DTransformedDescendantStatus();
2566 
2567     RefPtr<HitTestingTransformState> localTransformState;
2568     if (appliedTransform) {
2569         // We computed the correct state in the caller (above code), so just reference it.
2570         ASSERT(transformState);
2571         localTransformState = const_cast<HitTestingTransformState*>(transformState);
2572     } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
2573         // We need transform state for the first time, or to offset the container state, so create it here.
2574         localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
2575     }
2576 
2577     // Check for hit test on backface if backface-visibility is 'hidden'
2578     if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
2579         TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
2580         // If the z-vector of the matrix is negative, the back is facing towards the viewer.
2581         if (invertedMatrix.m33() < 0)
2582             return 0;
2583     }
2584 
2585     RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
2586     if (localTransformState && !preserves3D()) {
2587         // Keep a copy of the pre-flattening state, for computing z-offsets for the container
2588         unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
2589         // This layer is flattening, so flatten the state passed to descendants.
2590         localTransformState->flatten();
2591     }
2592 
2593     // Calculate the clip rects we should use.
2594     IntRect layerBounds;
2595     IntRect bgRect;
2596     IntRect fgRect;
2597     IntRect outlineRect;
2598     calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects);
2599 
2600     // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
2601     // descendants.
2602     double localZOffset = -numeric_limits<double>::infinity();
2603     double* zOffsetForDescendantsPtr = 0;
2604     double* zOffsetForContentsPtr = 0;
2605 
2606     bool depthSortDescendants = false;
2607     if (preserves3D()) {
2608         depthSortDescendants = true;
2609         // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
2610         zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
2611         zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
2612     } else if (m_has3DTransformedDescendant) {
2613         // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
2614         depthSortDescendants = true;
2615         zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
2616         zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
2617     } else if (zOffset) {
2618         zOffsetForDescendantsPtr = 0;
2619         // Container needs us to give back a z offset for the hit layer.
2620         zOffsetForContentsPtr = zOffset;
2621     }
2622 
2623     // This variable tracks which layer the mouse ends up being inside.
2624     RenderLayer* candidateLayer = 0;
2625 
2626     // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
2627     if (m_posZOrderList) {
2628         for (int i = m_posZOrderList->size() - 1; i >= 0; --i) {
2629             HitTestResult tempResult(result.point());
2630             RenderLayer* hitLayer = m_posZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
2631             if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
2632                 result = tempResult;
2633                 if (!depthSortDescendants)
2634                     return hitLayer;
2635 
2636                 candidateLayer = hitLayer;
2637             }
2638         }
2639     }
2640 
2641     // Now check our overflow objects.
2642     if (m_normalFlowList) {
2643         for (int i = m_normalFlowList->size() - 1; i >= 0; --i) {
2644             RenderLayer* currLayer = m_normalFlowList->at(i);
2645             HitTestResult tempResult(result.point());
2646             RenderLayer* hitLayer = currLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
2647             if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
2648                 result = tempResult;
2649                 if (!depthSortDescendants)
2650                     return hitLayer;
2651 
2652                 candidateLayer = hitLayer;
2653             }
2654         }
2655     }
2656 
2657     // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
2658     if (fgRect.contains(hitTestPoint) && isSelfPaintingLayer()) {
2659         // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
2660         HitTestResult tempResult(result.point());
2661         if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
2662             isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
2663             result = tempResult;
2664             if (!depthSortDescendants)
2665                 return this;
2666             // Foreground can depth-sort with descendant layers, so keep this as a candidate.
2667             candidateLayer = this;
2668         }
2669     }
2670 
2671     // Now check our negative z-index children.
2672     if (m_negZOrderList) {
2673         for (int i = m_negZOrderList->size() - 1; i >= 0; --i) {
2674             HitTestResult tempResult(result.point());
2675             RenderLayer* hitLayer = m_negZOrderList->at(i)->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, localTransformState.get(), zOffsetForDescendantsPtr);
2676             if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState.get())) {
2677                 result = tempResult;
2678                 if (!depthSortDescendants)
2679                     return hitLayer;
2680 
2681                 candidateLayer = hitLayer;
2682             }
2683         }
2684     }
2685 
2686     // If we found a layer, return. Child layers, and foreground always render in front of background.
2687     if (candidateLayer)
2688         return candidateLayer;
2689 
2690     if (bgRect.contains(hitTestPoint) && isSelfPaintingLayer()) {
2691         HitTestResult tempResult(result.point());
2692         if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
2693             isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
2694             result = tempResult;
2695             return this;
2696         }
2697     }
2698 
2699     return 0;
2700 }
2701 
hitTestContents(const HitTestRequest & request,HitTestResult & result,const IntRect & layerBounds,const IntPoint & hitTestPoint,HitTestFilter hitTestFilter) const2702 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const IntRect& layerBounds, const IntPoint& hitTestPoint, HitTestFilter hitTestFilter) const
2703 {
2704     if (!renderer()->hitTest(request, result, hitTestPoint,
2705                             layerBounds.x() - renderBoxX(),
2706                             layerBounds.y() - renderBoxY(),
2707                             hitTestFilter)) {
2708         // It's wrong to set innerNode, but then claim that you didn't hit anything.
2709         ASSERT(!result.innerNode());
2710         return false;
2711     }
2712 
2713     // For positioned generated content, we might still not have a
2714     // node by the time we get to the layer level, since none of
2715     // the content in the layer has an element. So just walk up
2716     // the tree.
2717     if (!result.innerNode() || !result.innerNonSharedNode()) {
2718         Node* e = enclosingElement();
2719         if (!result.innerNode())
2720             result.setInnerNode(e);
2721         if (!result.innerNonSharedNode())
2722             result.setInnerNonSharedNode(e);
2723     }
2724 
2725     return true;
2726 }
2727 
updateClipRects(const RenderLayer * rootLayer)2728 void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
2729 {
2730     if (m_clipRects) {
2731         ASSERT(rootLayer == m_clipRectsRoot);
2732         return; // We have the correct cached value.
2733     }
2734 
2735     // For transformed layers, the root layer was shifted to be us, so there is no need to
2736     // examine the parent.  We want to cache clip rects with us as the root.
2737     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
2738     if (parentLayer)
2739         parentLayer->updateClipRects(rootLayer);
2740 
2741     ClipRects clipRects;
2742     calculateClipRects(rootLayer, clipRects, true);
2743 
2744     if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
2745         m_clipRects = parentLayer->clipRects();
2746     else
2747         m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects);
2748     m_clipRects->ref();
2749 #ifndef NDEBUG
2750     m_clipRectsRoot = rootLayer;
2751 #endif
2752 }
2753 
calculateClipRects(const RenderLayer * rootLayer,ClipRects & clipRects,bool useCached) const2754 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached) const
2755 {
2756     if (!parent()) {
2757         // The root layer's clip rect is always infinite.
2758         clipRects.reset(ClipRects::infiniteRect());
2759         return;
2760     }
2761 
2762     // For transformed layers, the root layer was shifted to be us, so there is no need to
2763     // examine the parent.  We want to cache clip rects with us as the root.
2764     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
2765 
2766     // Ensure that our parent's clip has been calculated so that we can examine the values.
2767     if (parentLayer) {
2768         if (useCached && parentLayer->clipRects())
2769             clipRects = *parentLayer->clipRects();
2770         else
2771             parentLayer->calculateClipRects(rootLayer, clipRects);
2772     }
2773     else
2774         clipRects.reset(ClipRects::infiniteRect());
2775 
2776     // A fixed object is essentially the root of its containing block hierarchy, so when
2777     // we encounter such an object, we reset our clip rects to the fixedClipRect.
2778     if (renderer()->style()->position() == FixedPosition) {
2779         clipRects.setPosClipRect(clipRects.fixedClipRect());
2780         clipRects.setOverflowClipRect(clipRects.fixedClipRect());
2781         clipRects.setFixed(true);
2782     }
2783     else if (renderer()->style()->position() == RelativePosition)
2784         clipRects.setPosClipRect(clipRects.overflowClipRect());
2785     else if (renderer()->style()->position() == AbsolutePosition)
2786         clipRects.setOverflowClipRect(clipRects.posClipRect());
2787 
2788     // Update the clip rects that will be passed to child layers.
2789     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
2790         // This layer establishes a clip of some kind.
2791         int x = 0;
2792         int y = 0;
2793         convertToLayerCoords(rootLayer, x, y);
2794         RenderView* view = renderer()->view();
2795         ASSERT(view);
2796         if (view && clipRects.fixed() && rootLayer->renderer() == view) {
2797             x -= view->frameView()->scrollX();
2798             y -= view->frameView()->scrollY();
2799         }
2800 
2801         if (renderer()->hasOverflowClip()) {
2802             IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y);
2803             clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
2804             if (renderer()->isPositioned() || renderer()->isRelPositioned())
2805                 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
2806         }
2807         if (renderer()->hasClip()) {
2808             IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
2809             clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
2810             clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
2811             clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
2812         }
2813     }
2814 }
2815 
parentClipRects(const RenderLayer * rootLayer,ClipRects & clipRects,bool temporaryClipRects) const2816 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects) const
2817 {
2818     ASSERT(parent());
2819     if (temporaryClipRects) {
2820         parent()->calculateClipRects(rootLayer, clipRects);
2821         return;
2822     }
2823 
2824     parent()->updateClipRects(rootLayer);
2825     clipRects = *parent()->clipRects();
2826 }
2827 
backgroundClipRect(const RenderLayer * rootLayer,bool temporaryClipRects) const2828 IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const
2829 {
2830     IntRect backgroundRect;
2831     if (parent()) {
2832         ClipRects parentRects;
2833         parentClipRects(rootLayer, parentRects, temporaryClipRects);
2834         backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() :
2835                          (renderer()->isPositioned() ? parentRects.posClipRect() :
2836                                                        parentRects.overflowClipRect());
2837         RenderView* view = renderer()->view();
2838         ASSERT(view);
2839         if (view && parentRects.fixed() && rootLayer->renderer() == view)
2840             backgroundRect.move(view->frameView()->scrollX(), view->frameView()->scrollY());
2841     }
2842     return backgroundRect;
2843 }
2844 
calculateRects(const RenderLayer * rootLayer,const IntRect & paintDirtyRect,IntRect & layerBounds,IntRect & backgroundRect,IntRect & foregroundRect,IntRect & outlineRect,bool temporaryClipRects) const2845 void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
2846                                  IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const
2847 {
2848     if (rootLayer != this && parent()) {
2849         backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects);
2850         backgroundRect.intersect(paintDirtyRect);
2851     } else
2852         backgroundRect = paintDirtyRect;
2853 
2854     foregroundRect = backgroundRect;
2855     outlineRect = backgroundRect;
2856 
2857     int x = 0;
2858     int y = 0;
2859     convertToLayerCoords(rootLayer, x, y);
2860     layerBounds = IntRect(x, y, width(), height());
2861 
2862     // Update the clip rects that will be passed to child layers.
2863     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
2864         // This layer establishes a clip of some kind.
2865         if (renderer()->hasOverflowClip())
2866             foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y));
2867         if (renderer()->hasClip()) {
2868             // Clip applies to *us* as well, so go ahead and update the damageRect.
2869             IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
2870             backgroundRect.intersect(newPosClip);
2871             foregroundRect.intersect(newPosClip);
2872             outlineRect.intersect(newPosClip);
2873         }
2874 
2875         // If we establish a clip at all, then go ahead and make sure our background
2876         // rect is intersected with our layer's bounds.
2877         if (ShadowData* boxShadow = renderer()->style()->boxShadow()) {
2878             IntRect overflow = layerBounds;
2879             do {
2880                 if (boxShadow->style == Normal) {
2881                     IntRect shadowRect = layerBounds;
2882                     shadowRect.move(boxShadow->x, boxShadow->y);
2883                     shadowRect.inflate(boxShadow->blur + boxShadow->spread);
2884                     overflow.unite(shadowRect);
2885                 }
2886 
2887                 boxShadow = boxShadow->next;
2888             } while (boxShadow);
2889             backgroundRect.intersect(overflow);
2890         } else
2891             backgroundRect.intersect(layerBounds);
2892     }
2893 }
2894 
childrenClipRect() const2895 IntRect RenderLayer::childrenClipRect() const
2896 {
2897     RenderLayer* rootLayer = renderer()->view()->layer();
2898     RenderLayer* clippingRootLayer = clippingRoot();
2899     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
2900     calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
2901     return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox();
2902 }
2903 
selfClipRect() const2904 IntRect RenderLayer::selfClipRect() const
2905 {
2906     RenderLayer* rootLayer = renderer()->view()->layer();
2907     RenderLayer* clippingRootLayer = clippingRoot();
2908     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
2909     calculateRects(clippingRootLayer, rootLayer->boundingBox(rootLayer), layerBounds, backgroundRect, foregroundRect, outlineRect);
2910     return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox();
2911 }
2912 
addBlockSelectionGapsBounds(const IntRect & bounds)2913 void RenderLayer::addBlockSelectionGapsBounds(const IntRect& bounds)
2914 {
2915     m_blockSelectionGapsBounds.unite(bounds);
2916 }
2917 
clearBlockSelectionGapsBounds()2918 void RenderLayer::clearBlockSelectionGapsBounds()
2919 {
2920     m_blockSelectionGapsBounds = IntRect();
2921     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
2922         child->clearBlockSelectionGapsBounds();
2923 }
2924 
repaintBlockSelectionGaps()2925 void RenderLayer::repaintBlockSelectionGaps()
2926 {
2927     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
2928         child->repaintBlockSelectionGaps();
2929 
2930     if (m_blockSelectionGapsBounds.isEmpty())
2931         return;
2932 
2933     IntRect rect = m_blockSelectionGapsBounds;
2934     rect.move(-scrolledContentOffset());
2935     if (renderer()->hasOverflowClip())
2936         rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0));
2937     if (renderer()->hasClip())
2938         rect.intersect(toRenderBox(renderer())->clipRect(0, 0));
2939     if (!rect.isEmpty())
2940         renderer()->repaintRectangle(rect);
2941 }
2942 
intersectsDamageRect(const IntRect & layerBounds,const IntRect & damageRect,const RenderLayer * rootLayer) const2943 bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const
2944 {
2945     // Always examine the canvas and the root.
2946     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
2947     // paints the root's background.
2948     if (renderer()->isRenderView() || renderer()->isRoot())
2949         return true;
2950 
2951     // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
2952     // can go ahead and return true.
2953     RenderView* view = renderer()->view();
2954     ASSERT(view);
2955     if (view && !renderer()->isRenderInline()) {
2956         IntRect b = layerBounds;
2957         b.inflate(view->maximalOutlineSize());
2958         if (b.intersects(damageRect))
2959             return true;
2960     }
2961 
2962     // Otherwise we need to compute the bounding box of this single layer and see if it intersects
2963     // the damage rect.
2964     return boundingBox(rootLayer).intersects(damageRect);
2965 }
2966 
localBoundingBox() const2967 IntRect RenderLayer::localBoundingBox() const
2968 {
2969     // There are three special cases we need to consider.
2970     // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
2971     // inline.  In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the
2972     // line boxes of all three lines (including overflow on those lines).
2973     // (2) Left/Top Overflow.  The width/height of layers already includes right/bottom overflow.  However, in the case of left/top
2974     // overflow, we have to create a bounding box that will extend to include this overflow.
2975     // (3) Floats.  When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
2976     // as part of our bounding box.  We do this because we are the responsible layer for both hit testing and painting those
2977     // floats.
2978     IntRect result;
2979     if (renderer()->isRenderInline()) {
2980         // Go from our first line box to our last line box.
2981         RenderInline* inlineFlow = toRenderInline(renderer());
2982         InlineFlowBox* firstBox = inlineFlow->firstLineBox();
2983         if (!firstBox)
2984             return result;
2985         int top = firstBox->topVisibleOverflow();
2986         int bottom = inlineFlow->lastLineBox()->bottomVisibleOverflow();
2987         int left = firstBox->x();
2988         for (InlineRunBox* curr = firstBox->nextLineBox(); curr; curr = curr->nextLineBox())
2989             left = min(left, curr->x());
2990         result = IntRect(left, top, width(), bottom - top);
2991     } else if (renderer()->isTableRow()) {
2992         // Our bounding box is just the union of all of our cells' border/overflow rects.
2993         for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
2994             if (child->isTableCell()) {
2995                 IntRect bbox = toRenderBox(child)->borderBoxRect();
2996                 result.unite(bbox);
2997                 IntRect overflowRect = renderBox()->visibleOverflowRect();
2998                 if (bbox != overflowRect)
2999                     result.unite(overflowRect);
3000             }
3001         }
3002     } else {
3003         RenderBox* box = renderBox();
3004         ASSERT(box);
3005         if (box->hasMask())
3006             result = box->maskClipRect();
3007         else {
3008             IntRect bbox = box->borderBoxRect();
3009             result = bbox;
3010             IntRect overflowRect = box->visibleOverflowRect();
3011             if (bbox != overflowRect)
3012                 result.unite(overflowRect);
3013         }
3014     }
3015 
3016     RenderView* view = renderer()->view();
3017     ASSERT(view);
3018     if (view)
3019         result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
3020 
3021     return result;
3022 }
3023 
boundingBox(const RenderLayer * ancestorLayer) const3024 IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
3025 {
3026     IntRect result = localBoundingBox();
3027 
3028     int deltaX = 0, deltaY = 0;
3029     convertToLayerCoords(ancestorLayer, deltaX, deltaY);
3030     result.move(deltaX, deltaY);
3031     return result;
3032 }
3033 
absoluteBoundingBox() const3034 IntRect RenderLayer::absoluteBoundingBox() const
3035 {
3036     return boundingBox(root());
3037 }
3038 
clearClipRectsIncludingDescendants()3039 void RenderLayer::clearClipRectsIncludingDescendants()
3040 {
3041     if (!m_clipRects)
3042         return;
3043 
3044     clearClipRects();
3045 
3046     for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
3047         l->clearClipRectsIncludingDescendants();
3048 }
3049 
clearClipRects()3050 void RenderLayer::clearClipRects()
3051 {
3052     if (m_clipRects) {
3053         m_clipRects->deref(renderer()->renderArena());
3054         m_clipRects = 0;
3055 #ifndef NDEBUG
3056         m_clipRectsRoot = 0;
3057 #endif
3058     }
3059 }
3060 
3061 #if USE(ACCELERATED_COMPOSITING)
ensureBacking()3062 RenderLayerBacking* RenderLayer::ensureBacking()
3063 {
3064     if (!m_backing)
3065         m_backing.set(new RenderLayerBacking(this));
3066     return m_backing.get();
3067 }
3068 
clearBacking()3069 void RenderLayer::clearBacking()
3070 {
3071     m_backing.clear();
3072 }
3073 
hasCompositedMask() const3074 bool RenderLayer::hasCompositedMask() const
3075 {
3076     return m_backing && m_backing->hasMaskLayer();
3077 }
3078 #endif
3079 
setParent(RenderLayer * parent)3080 void RenderLayer::setParent(RenderLayer* parent)
3081 {
3082     if (parent == m_parent)
3083         return;
3084 
3085 #if USE(ACCELERATED_COMPOSITING)
3086     if (m_parent && !renderer()->documentBeingDestroyed())
3087         compositor()->layerWillBeRemoved(m_parent, this);
3088 #endif
3089 
3090     m_parent = parent;
3091 
3092 #if USE(ACCELERATED_COMPOSITING)
3093     if (m_parent && !renderer()->documentBeingDestroyed())
3094         compositor()->layerWasAdded(m_parent, this);
3095 #endif
3096 }
3097 
commonAncestor(RenderObject * obj1,RenderObject * obj2)3098 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
3099 {
3100     if (!obj1 || !obj2)
3101         return 0;
3102 
3103     for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
3104         for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
3105             if (currObj1 == currObj2)
3106                 return currObj1;
3107 
3108     return 0;
3109 }
3110 
updateHoverActiveState(const HitTestRequest & request,HitTestResult & result)3111 void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
3112 {
3113     // We don't update :hover/:active state when the result is marked as readOnly.
3114     if (request.readOnly())
3115         return;
3116 
3117     Document* doc = renderer()->document();
3118 
3119     Node* activeNode = doc->activeNode();
3120     if (activeNode && !request.active()) {
3121         // We are clearing the :active chain because the mouse has been released.
3122         for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
3123             if (curr->node() && !curr->isText())
3124                 curr->node()->setInActiveChain(false);
3125         }
3126         doc->setActiveNode(0);
3127     } else {
3128         Node* newActiveNode = result.innerNode();
3129         if (!activeNode && newActiveNode && request.active()) {
3130             // We are setting the :active chain and freezing it. If future moves happen, they
3131             // will need to reference this chain.
3132             for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
3133                 if (curr->node() && !curr->isText()) {
3134                     curr->node()->setInActiveChain(true);
3135                 }
3136             }
3137             doc->setActiveNode(newActiveNode);
3138         }
3139     }
3140 
3141     // If the mouse is down and if this is a mouse move event, we want to restrict changes in
3142     // :hover/:active to only apply to elements that are in the :active chain that we froze
3143     // at the time the mouse went down.
3144     bool mustBeInActiveChain = request.active() && request.mouseMove();
3145 
3146     // Check to see if the hovered node has changed.  If not, then we don't need to
3147     // do anything.
3148     RefPtr<Node> oldHoverNode = doc->hoverNode();
3149     Node* newHoverNode = result.innerNode();
3150 
3151     // Update our current hover node.
3152     doc->setHoverNode(newHoverNode);
3153 
3154     // We have two different objects.  Fetch their renderers.
3155     RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
3156     RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
3157 
3158     // Locate the common ancestor render object for the two renderers.
3159     RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
3160 
3161     if (oldHoverObj != newHoverObj) {
3162         // The old hover path only needs to be cleared up to (and not including) the common ancestor;
3163         for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
3164             if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) {
3165                 curr->node()->setActive(false);
3166                 curr->node()->setHovered(false);
3167             }
3168         }
3169     }
3170 
3171     // Now set the hover state for our new object up to the root.
3172     for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
3173         if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain())) {
3174             curr->node()->setActive(request.active());
3175             curr->node()->setHovered(true);
3176         }
3177     }
3178 }
3179 
3180 // Helper for the sorting of layers by z-index.
compareZIndex(RenderLayer * first,RenderLayer * second)3181 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
3182 {
3183     return first->zIndex() < second->zIndex();
3184 }
3185 
dirtyZOrderLists()3186 void RenderLayer::dirtyZOrderLists()
3187 {
3188     if (m_posZOrderList)
3189         m_posZOrderList->clear();
3190     if (m_negZOrderList)
3191         m_negZOrderList->clear();
3192     m_zOrderListsDirty = true;
3193 
3194 #if USE(ACCELERATED_COMPOSITING)
3195     if (!renderer()->documentBeingDestroyed())
3196         compositor()->setCompositingLayersNeedRebuild();
3197 #endif
3198 }
3199 
dirtyStackingContextZOrderLists()3200 void RenderLayer::dirtyStackingContextZOrderLists()
3201 {
3202     RenderLayer* sc = stackingContext();
3203     if (sc)
3204         sc->dirtyZOrderLists();
3205 }
3206 
dirtyNormalFlowList()3207 void RenderLayer::dirtyNormalFlowList()
3208 {
3209     if (m_normalFlowList)
3210         m_normalFlowList->clear();
3211     m_normalFlowListDirty = true;
3212 
3213 #if USE(ACCELERATED_COMPOSITING)
3214     if (!renderer()->documentBeingDestroyed())
3215         compositor()->setCompositingLayersNeedRebuild();
3216 #endif
3217 }
3218 
updateZOrderLists()3219 void RenderLayer::updateZOrderLists()
3220 {
3221     if (!isStackingContext() || !m_zOrderListsDirty)
3222         return;
3223 
3224     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3225         if (!m_reflection || reflectionLayer() != child)
3226             child->collectLayers(m_posZOrderList, m_negZOrderList);
3227 
3228     // Sort the two lists.
3229     if (m_posZOrderList)
3230         std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
3231 
3232     if (m_negZOrderList)
3233         std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
3234 
3235     m_zOrderListsDirty = false;
3236 }
3237 
updateNormalFlowList()3238 void RenderLayer::updateNormalFlowList()
3239 {
3240     if (!m_normalFlowListDirty)
3241         return;
3242 
3243     for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
3244         // Ignore non-overflow layers and reflections.
3245         if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
3246             if (!m_normalFlowList)
3247                 m_normalFlowList = new Vector<RenderLayer*>;
3248             m_normalFlowList->append(child);
3249         }
3250     }
3251 
3252     m_normalFlowListDirty = false;
3253 }
3254 
collectLayers(Vector<RenderLayer * > * & posBuffer,Vector<RenderLayer * > * & negBuffer)3255 void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
3256 {
3257     updateVisibilityStatus();
3258 
3259     // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
3260     if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isNormalFlowOnly()) {
3261         // Determine which buffer the child should be in.
3262         Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
3263 
3264         // Create the buffer if it doesn't exist yet.
3265         if (!buffer)
3266             buffer = new Vector<RenderLayer*>;
3267 
3268         // Append ourselves at the end of the appropriate buffer.
3269         buffer->append(this);
3270     }
3271 
3272     // Recur into our children to collect more layers, but only if we don't establish
3273     // a stacking context.
3274     if (m_hasVisibleDescendant && !isStackingContext()) {
3275         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
3276             // Ignore reflections.
3277             if (!m_reflection || reflectionLayer() != child)
3278                 child->collectLayers(posBuffer, negBuffer);
3279         }
3280     }
3281 }
3282 
updateLayerListsIfNeeded()3283 void RenderLayer::updateLayerListsIfNeeded()
3284 {
3285     updateZOrderLists();
3286     updateNormalFlowList();
3287 }
3288 
updateCompositingAndLayerListsIfNeeded()3289 void RenderLayer::updateCompositingAndLayerListsIfNeeded()
3290 {
3291 #if USE(ACCELERATED_COMPOSITING)
3292     if (compositor()->inCompositingMode()) {
3293         if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty)
3294             compositor()->updateCompositingLayers(CompositingUpdateOnPaitingOrHitTest, this);
3295         return;
3296     }
3297 #endif
3298     updateLayerListsIfNeeded();
3299 }
3300 
repaintIncludingDescendants()3301 void RenderLayer::repaintIncludingDescendants()
3302 {
3303     renderer()->repaint();
3304     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
3305         curr->repaintIncludingDescendants();
3306 }
3307 
3308 #if USE(ACCELERATED_COMPOSITING)
setBackingNeedsRepaint()3309 void RenderLayer::setBackingNeedsRepaint()
3310 {
3311     ASSERT(isComposited());
3312     if (backing()->paintingGoesToWindow()) {
3313         // If we're trying to repaint the placeholder document layer, propagate the
3314         // repaint to the native view system.
3315         RenderView* view = renderer()->view();
3316         if (view)
3317             view->repaintViewRectangle(absoluteBoundingBox());
3318     } else
3319         backing()->setContentsNeedDisplay();
3320 }
3321 
setBackingNeedsRepaintInRect(const IntRect & r)3322 void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r)
3323 {
3324     ASSERT(isComposited());
3325     if (backing()->paintingGoesToWindow()) {
3326         // If we're trying to repaint the placeholder document layer, propagate the
3327         // repaint to the native view system.
3328         IntRect absRect(r);
3329         int x = 0;
3330         int y = 0;
3331         convertToLayerCoords(root(), x, y);
3332         absRect.move(x, y);
3333 
3334         RenderView* view = renderer()->view();
3335         if (view)
3336             view->repaintViewRectangle(absRect);
3337     } else
3338         backing()->setContentsNeedDisplayInRect(r);
3339 }
3340 
3341 // Since we're only painting non-composited layers, we know that they all share the same repaintContainer.
repaintIncludingNonCompositingDescendants(RenderBoxModelObject * repaintContainer)3342 void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer)
3343 {
3344     renderer()->repaintUsingContainer(repaintContainer, renderer()->clippedOverflowRectForRepaint(repaintContainer));
3345 
3346     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) {
3347         if (!curr->isComposited())
3348             curr->repaintIncludingNonCompositingDescendants(repaintContainer);
3349     }
3350 }
3351 #endif
3352 
shouldBeNormalFlowOnly() const3353 bool RenderLayer::shouldBeNormalFlowOnly() const
3354 {
3355     return (renderer()->hasOverflowClip() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isVideo() || renderer()->isEmbeddedObject()) &&
3356            !renderer()->isPositioned() &&
3357            !renderer()->isRelPositioned() &&
3358            !renderer()->hasTransform() &&
3359            !isTransparent();
3360 }
3361 
isSelfPaintingLayer() const3362 bool RenderLayer::isSelfPaintingLayer() const
3363 {
3364     return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow() || renderer()->isVideo() || renderer()->isEmbeddedObject();
3365 }
3366 
styleChanged(StyleDifference diff,const RenderStyle *)3367 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle*)
3368 {
3369     bool isNormalFlowOnly = shouldBeNormalFlowOnly();
3370     if (isNormalFlowOnly != m_isNormalFlowOnly) {
3371         m_isNormalFlowOnly = isNormalFlowOnly;
3372         RenderLayer* p = parent();
3373         if (p)
3374             p->dirtyNormalFlowList();
3375         dirtyStackingContextZOrderLists();
3376     }
3377 
3378     if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE && renderer()->isBox()) {
3379         if (!m_marquee)
3380             m_marquee = new RenderMarquee(this);
3381         m_marquee->updateMarqueeStyle();
3382     }
3383     else if (m_marquee) {
3384         delete m_marquee;
3385         m_marquee = 0;
3386     }
3387 
3388     if (!hasReflection() && m_reflection)
3389         removeReflection();
3390     else if (hasReflection()) {
3391         if (!m_reflection)
3392             createReflection();
3393         updateReflectionStyle();
3394     }
3395 
3396     // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
3397     if (m_hBar)
3398         m_hBar->styleChanged();
3399     if (m_vBar)
3400         m_vBar->styleChanged();
3401 
3402     updateScrollCornerStyle();
3403     updateResizerStyle();
3404 
3405 #if USE(ACCELERATED_COMPOSITING)
3406     updateTransform();
3407 
3408     if (compositor()->updateLayerCompositingState(this))
3409         compositor()->setCompositingLayersNeedRebuild();
3410     else if (m_backing)
3411         m_backing->updateGraphicsLayerGeometry();
3412 
3413     if (m_backing && diff >= StyleDifferenceRepaint)
3414         m_backing->setContentsNeedDisplay();
3415 #else
3416     UNUSED_PARAM(diff);
3417 #endif
3418 }
3419 
updateScrollCornerStyle()3420 void RenderLayer::updateScrollCornerStyle()
3421 {
3422     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
3423     RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : 0;
3424     if (corner) {
3425         if (!m_scrollCorner) {
3426             m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
3427             m_scrollCorner->setParent(renderer());
3428         }
3429         m_scrollCorner->setStyle(corner.release());
3430     } else if (m_scrollCorner) {
3431         m_scrollCorner->destroy();
3432         m_scrollCorner = 0;
3433     }
3434 }
3435 
updateResizerStyle()3436 void RenderLayer::updateResizerStyle()
3437 {
3438     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
3439     RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : 0;
3440     if (resizer) {
3441         if (!m_resizer) {
3442             m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
3443             m_resizer->setParent(renderer());
3444         }
3445         m_resizer->setStyle(resizer.release());
3446     } else if (m_resizer) {
3447         m_resizer->destroy();
3448         m_resizer = 0;
3449     }
3450 }
3451 
reflectionLayer() const3452 RenderLayer* RenderLayer::reflectionLayer() const
3453 {
3454     return m_reflection ? m_reflection->layer() : 0;
3455 }
3456 
createReflection()3457 void RenderLayer::createReflection()
3458 {
3459     ASSERT(!m_reflection);
3460     m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document());
3461     m_reflection->setParent(renderer()); // We create a 1-way connection.
3462 }
3463 
removeReflection()3464 void RenderLayer::removeReflection()
3465 {
3466     if (!m_reflection->documentBeingDestroyed())
3467         m_reflection->removeLayers(this);
3468 
3469     m_reflection->setParent(0);
3470     m_reflection->destroy();
3471     m_reflection = 0;
3472 }
3473 
updateReflectionStyle()3474 void RenderLayer::updateReflectionStyle()
3475 {
3476     RefPtr<RenderStyle> newStyle = RenderStyle::create();
3477     newStyle->inheritFrom(renderer()->style());
3478 
3479     // Map in our transform.
3480     TransformOperations transform;
3481     switch (renderer()->style()->boxReflect()->direction()) {
3482         case ReflectionBelow:
3483             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
3484             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
3485             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
3486             break;
3487         case ReflectionAbove:
3488             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
3489             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
3490             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
3491             break;
3492         case ReflectionRight:
3493             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
3494             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
3495             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
3496             break;
3497         case ReflectionLeft:
3498             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
3499             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
3500             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
3501             break;
3502     }
3503     newStyle->setTransform(transform);
3504 
3505     // Map in our mask.
3506     newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask());
3507 
3508     m_reflection->setStyle(newStyle.release());
3509 }
3510 
3511 } // namespace WebCore
3512 
3513 #ifndef NDEBUG
showLayerTree(const WebCore::RenderLayer * layer)3514 void showLayerTree(const WebCore::RenderLayer* layer)
3515 {
3516     if (!layer)
3517         return;
3518 
3519     if (WebCore::Frame* frame = layer->renderer()->document()->frame()) {
3520         WebCore::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers);
3521         fprintf(stderr, "%s\n", output.utf8().data());
3522     }
3523 }
3524 #endif
3525