1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 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 "ColumnInfo.h"
48 #include "CSSPropertyNames.h"
49 #include "CSSStyleDeclaration.h"
50 #include "CSSStyleSelector.h"
51 #include "Chrome.h"
52 #include "Document.h"
53 #include "EventHandler.h"
54 #include "EventQueue.h"
55 #include "FloatPoint3D.h"
56 #include "FloatRect.h"
57 #include "FocusController.h"
58 #include "Frame.h"
59 #include "FrameTree.h"
60 #include "FrameView.h"
61 #include "Gradient.h"
62 #include "GraphicsContext.h"
63 #include "HTMLFrameOwnerElement.h"
64 #include "HTMLNames.h"
65 #include "HitTestRequest.h"
66 #include "HitTestResult.h"
67 #include "OverflowEvent.h"
68 #include "OverlapTestRequestClient.h"
69 #include "Page.h"
70 #include "PlatformMouseEvent.h"
71 #include "RenderArena.h"
72 #include "RenderInline.h"
73 #include "RenderMarquee.h"
74 #include "RenderReplica.h"
75 #include "RenderScrollbar.h"
76 #include "RenderScrollbarPart.h"
77 #include "RenderTheme.h"
78 #include "RenderTreeAsText.h"
79 #include "RenderView.h"
80 #include "ScaleTransformOperation.h"
81 #include "Scrollbar.h"
82 #include "ScrollbarTheme.h"
83 #include "SelectionController.h"
84 #include "TextStream.h"
85 #include "TransformState.h"
86 #include "TransformationMatrix.h"
87 #include "TranslateTransformOperation.h"
88 #include <wtf/StdLibExtras.h>
89 #include <wtf/UnusedParam.h>
90 #include <wtf/text/CString.h>
91 
92 #if USE(ACCELERATED_COMPOSITING)
93 #include "RenderLayerBacking.h"
94 #include "RenderLayerCompositor.h"
95 #endif
96 
97 #if ENABLE(SVG)
98 #include "SVGNames.h"
99 #endif
100 
101 #define MIN_INTERSECT_FOR_REVEAL 32
102 
103 using namespace std;
104 
105 namespace WebCore {
106 
107 using namespace HTMLNames;
108 
109 const int MinimumWidthWhileResizing = 100;
110 const int MinimumHeightWhileResizing = 40;
111 
operator new(size_t sz,RenderArena * renderArena)112 void* ClipRects::operator new(size_t sz, RenderArena* renderArena) throw()
113 {
114     return renderArena->allocate(sz);
115 }
116 
operator delete(void * ptr,size_t sz)117 void ClipRects::operator delete(void* ptr, size_t sz)
118 {
119     // Stash size where destroy can find it.
120     *(size_t *)ptr = sz;
121 }
122 
destroy(RenderArena * renderArena)123 void ClipRects::destroy(RenderArena* renderArena)
124 {
125     delete this;
126 
127     // Recover the size left there for us by operator delete and free the memory.
128     renderArena->free(*(size_t *)this, this);
129 }
130 
RenderLayer(RenderBoxModelObject * renderer)131 RenderLayer::RenderLayer(RenderBoxModelObject* renderer)
132     : m_renderer(renderer)
133     , m_parent(0)
134     , m_previous(0)
135     , m_next(0)
136     , m_first(0)
137     , m_last(0)
138     , m_relX(0)
139     , m_relY(0)
140     , m_x(0)
141     , m_y(0)
142     , m_width(0)
143     , m_height(0)
144     , m_scrollX(0)
145     , m_scrollY(0)
146     , m_scrollLeftOverflow(0)
147     , m_scrollTopOverflow(0)
148     , m_scrollWidth(0)
149     , m_scrollHeight(0)
150     , m_inResizeMode(false)
151     , m_posZOrderList(0)
152     , m_negZOrderList(0)
153     , m_normalFlowList(0)
154     , m_clipRects(0)
155 #ifndef NDEBUG
156     , m_clipRectsRoot(0)
157 #endif
158     , m_scrollDimensionsDirty(true)
159     , m_zOrderListsDirty(true)
160     , m_normalFlowListDirty(true)
161     , m_isNormalFlowOnly(shouldBeNormalFlowOnly())
162     , m_usedTransparency(false)
163     , m_paintingInsideReflection(false)
164     , m_inOverflowRelayout(false)
165     , m_needsFullRepaint(false)
166     , m_overflowStatusDirty(true)
167     , m_visibleContentStatusDirty(true)
168     , m_hasVisibleContent(false)
169     , m_visibleDescendantStatusDirty(false)
170     , m_hasVisibleDescendant(false)
171     , m_isPaginated(false)
172     , m_3DTransformedDescendantStatusDirty(true)
173     , m_has3DTransformedDescendant(false)
174 #if USE(ACCELERATED_COMPOSITING)
175     , m_hasCompositingDescendant(false)
176     , m_mustOverlapCompositedLayers(false)
177 #endif
178     , m_containsDirtyOverlayScrollbars(false)
179     , m_marquee(0)
180     , m_staticInlinePosition(0)
181     , m_staticBlockPosition(0)
182     , m_reflection(0)
183     , m_scrollCorner(0)
184     , m_resizer(0)
185 {
186     ScrollableArea::setConstrainsScrollingToContentEdge(false);
187 
188     if (!renderer->firstChild() && renderer->style()) {
189         m_visibleContentStatusDirty = false;
190         m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
191     }
192 
193     if (Frame* frame = renderer->frame()) {
194         if (Page* page = frame->page()) {
195             m_page = page;
196             m_page->addScrollableArea(this);
197         }
198     }
199 }
200 
~RenderLayer()201 RenderLayer::~RenderLayer()
202 {
203     if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
204         if (Frame* frame = renderer()->frame())
205             frame->eventHandler()->resizeLayerDestroyed();
206     }
207 
208     if (m_page)
209         m_page->removeScrollableArea(this);
210 
211     destroyScrollbar(HorizontalScrollbar);
212     destroyScrollbar(VerticalScrollbar);
213 
214     if (m_reflection)
215         removeReflection();
216 
217     // Child layers will be deleted by their corresponding render objects, so
218     // we don't need to delete them ourselves.
219 
220     delete m_posZOrderList;
221     delete m_negZOrderList;
222     delete m_normalFlowList;
223     delete m_marquee;
224 
225 #if USE(ACCELERATED_COMPOSITING)
226     clearBacking();
227 #endif
228 
229     // Make sure we have no lingering clip rects.
230     ASSERT(!m_clipRects);
231 
232     if (m_scrollCorner)
233         m_scrollCorner->destroy();
234     if (m_resizer)
235         m_resizer->destroy();
236 }
237 
238 #if USE(ACCELERATED_COMPOSITING)
compositor() const239 RenderLayerCompositor* RenderLayer::compositor() const
240 {
241     ASSERT(renderer()->view());
242     return renderer()->view()->compositor();
243 }
244 
contentChanged(ContentChangeType changeType)245 void RenderLayer::contentChanged(ContentChangeType changeType)
246 {
247     // This can get called when video becomes accelerated, so the layers may change.
248     if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this))
249         compositor()->setCompositingLayersNeedRebuild();
250 
251     if (m_backing)
252         m_backing->contentChanged(changeType);
253 }
254 #endif // USE(ACCELERATED_COMPOSITING)
255 
hasAcceleratedCompositing() const256 bool RenderLayer::hasAcceleratedCompositing() const
257 {
258 #if USE(ACCELERATED_COMPOSITING)
259     return compositor()->hasAcceleratedCompositing();
260 #else
261     return false;
262 #endif
263 }
264 
canRender3DTransforms() const265 bool RenderLayer::canRender3DTransforms() const
266 {
267 #if USE(ACCELERATED_COMPOSITING)
268     return compositor()->canRender3DTransforms();
269 #else
270     return false;
271 #endif
272 }
273 
updateLayerPositions(UpdateLayerPositionsFlags flags,IntPoint * cachedOffset)274 void RenderLayer::updateLayerPositions(UpdateLayerPositionsFlags flags, IntPoint* cachedOffset)
275 {
276     updateLayerPosition(); // For relpositioned layers or non-positioned layers,
277                            // we need to keep in sync, since we may have shifted relative
278                            // to our parent layer.
279     IntPoint oldCachedOffset;
280     if (cachedOffset) {
281         // We can't cache our offset to the repaint container if the mapping is anything more complex than a simple translation
282         bool disableOffsetCache = renderer()->hasColumns() || renderer()->hasTransform() || isComposited();
283 #if ENABLE(SVG)
284         disableOffsetCache = disableOffsetCache || renderer()->isSVGRoot();
285 #endif
286         if (disableOffsetCache)
287             cachedOffset = 0; // If our cached offset is invalid make sure it's not passed to any of our children
288         else {
289             oldCachedOffset = *cachedOffset;
290             // Frequently our parent layer's renderer will be the same as our renderer's containing block.  In that case,
291             // we just update the cache using our offset to our parent (which is m_x / m_y).  Otherwise, regenerated cached
292             // offsets to the root from the render tree.
293             if (!m_parent || m_parent->renderer() == renderer()->containingBlock())
294                 cachedOffset->move(m_x, m_y); // Fast case
295             else {
296                 int x = 0;
297                 int y = 0;
298                 convertToLayerCoords(root(), x, y);
299                 *cachedOffset = IntPoint(x, y);
300             }
301         }
302     }
303 
304     int x = 0;
305     int y = 0;
306     if (cachedOffset) {
307         x += cachedOffset->x();
308         y += cachedOffset->y();
309 #ifndef NDEBUG
310         int nonCachedX = 0;
311         int nonCachedY = 0;
312         convertToLayerCoords(root(), nonCachedX, nonCachedY);
313         ASSERT(x == nonCachedX);
314         ASSERT(y == nonCachedY);
315 #endif
316     } else
317         convertToLayerCoords(root(), x, y);
318     positionOverflowControls(x, y);
319 
320     updateVisibilityStatus();
321 
322     if (flags & UpdatePagination)
323         updatePagination();
324     else
325         m_isPaginated = false;
326 
327     if (m_hasVisibleContent) {
328         RenderView* view = renderer()->view();
329         ASSERT(view);
330         // FIXME: Optimize using LayoutState and remove the disableLayoutState() call
331         // from updateScrollInfoAfterLayout().
332         ASSERT(!view->layoutStateEnabled());
333 
334         RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
335         IntRect newRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
336         IntRect newOutlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, cachedOffset);
337         // FIXME: Should ASSERT that value calculated for newOutlineBox using the cached offset is the same
338         // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
339         if (flags & CheckForRepaint) {
340             if (view && !view->printing()) {
341                 if (m_needsFullRepaint) {
342                     renderer()->repaintUsingContainer(repaintContainer, m_repaintRect);
343                     if (newRect != m_repaintRect)
344                         renderer()->repaintUsingContainer(repaintContainer, newRect);
345                 } else
346                     renderer()->repaintAfterLayoutIfNeeded(repaintContainer, m_repaintRect, m_outlineBox, &newRect, &newOutlineBox);
347             }
348         }
349         m_repaintRect = newRect;
350         m_outlineBox = newOutlineBox;
351     } else {
352         m_repaintRect = IntRect();
353         m_outlineBox = IntRect();
354     }
355 
356     m_needsFullRepaint = false;
357 
358     // Go ahead and update the reflection's position and size.
359     if (m_reflection)
360         m_reflection->layout();
361 
362 #if USE(ACCELERATED_COMPOSITING)
363     // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
364     bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
365     if (isComposited())
366         flags &= ~IsCompositingUpdateRoot;
367 #endif
368 
369     if (renderer()->hasColumns())
370         flags |= UpdatePagination;
371 
372     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
373         child->updateLayerPositions(flags, cachedOffset);
374 
375 #if USE(ACCELERATED_COMPOSITING)
376     if ((flags & UpdateCompositingLayers) && isComposited())
377         backing()->updateAfterLayout(RenderLayerBacking::CompositingChildren, isUpdateRoot);
378 #endif
379 
380     // With all our children positioned, now update our marquee if we need to.
381     if (m_marquee)
382         m_marquee->updateMarqueePosition();
383 
384     if (cachedOffset)
385         *cachedOffset = oldCachedOffset;
386 }
387 
repaintRectIncludingDescendants() const388 IntRect RenderLayer::repaintRectIncludingDescendants() const
389 {
390     IntRect repaintRect = m_repaintRect;
391     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
392         repaintRect.unite(child->repaintRectIncludingDescendants());
393     return repaintRect;
394 }
395 
computeRepaintRects()396 void RenderLayer::computeRepaintRects()
397 {
398     RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
399     m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
400     m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
401 }
402 
updateRepaintRectsAfterScroll(bool fixed)403 void RenderLayer::updateRepaintRectsAfterScroll(bool fixed)
404 {
405     if (fixed || renderer()->style()->position() == FixedPosition) {
406         computeRepaintRects();
407         fixed = true;
408     } else if (renderer()->hasTransform() && !renderer()->isRenderView()) {
409         // Transforms act as fixed position containers, so nothing inside a
410         // transformed element can be fixed relative to the viewport if the
411         // transformed element is not fixed itself or child of a fixed element.
412         return;
413     }
414 
415     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
416         child->updateRepaintRectsAfterScroll(fixed);
417 }
418 
updateTransform()419 void RenderLayer::updateTransform()
420 {
421     // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
422     // so check style too.
423     bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
424     bool had3DTransform = has3DTransform();
425 
426     bool hadTransform = m_transform;
427     if (hasTransform != hadTransform) {
428         if (hasTransform)
429             m_transform = adoptPtr(new TransformationMatrix);
430         else
431             m_transform.clear();
432     }
433 
434     if (hasTransform) {
435         RenderBox* box = renderBox();
436         ASSERT(box);
437         m_transform->makeIdentity();
438         box->style()->applyTransform(*m_transform, box->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
439         makeMatrixRenderable(*m_transform, canRender3DTransforms());
440     }
441 
442     if (had3DTransform != has3DTransform())
443         dirty3DTransformedDescendantStatus();
444 }
445 
currentTransform() const446 TransformationMatrix RenderLayer::currentTransform() const
447 {
448     if (!m_transform)
449         return TransformationMatrix();
450 
451 #if USE(ACCELERATED_COMPOSITING)
452     if (renderer()->style()->isRunningAcceleratedAnimation()) {
453         TransformationMatrix currTransform;
454         RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
455         style->applyTransform(currTransform, renderBox()->borderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
456         makeMatrixRenderable(currTransform, canRender3DTransforms());
457         return currTransform;
458     }
459 #endif
460 
461     return *m_transform;
462 }
463 
renderableTransform(PaintBehavior paintBehavior) const464 TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
465 {
466     if (!m_transform)
467         return TransformationMatrix();
468 
469     if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
470         TransformationMatrix matrix = *m_transform;
471         makeMatrixRenderable(matrix, false /* flatten 3d */);
472         return matrix;
473     }
474 
475     return *m_transform;
476 }
477 
checkContainingBlockChainForPagination(RenderBoxModelObject * renderer,RenderBox * ancestorColumnsRenderer)478 static bool checkContainingBlockChainForPagination(RenderBoxModelObject* renderer, RenderBox* ancestorColumnsRenderer)
479 {
480     RenderView* view = renderer->view();
481     RenderBoxModelObject* prevBlock = renderer;
482     RenderBlock* containingBlock;
483     for (containingBlock = renderer->containingBlock();
484          containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer;
485          containingBlock = containingBlock->containingBlock())
486         prevBlock = containingBlock;
487 
488     // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
489     if (containingBlock != ancestorColumnsRenderer)
490         return false;
491 
492     // If the previous block is absolutely positioned, then we can't be paginated by the columns block.
493     if (prevBlock->isPositioned())
494         return false;
495 
496     // Otherwise we are paginated by the columns block.
497     return true;
498 }
499 
updatePagination()500 void RenderLayer::updatePagination()
501 {
502     m_isPaginated = false;
503     if (isComposited() || !parent())
504         return; // FIXME: We will have to deal with paginated compositing layers someday.
505                 // FIXME: For now the RenderView can't be paginated.  Eventually printing will move to a model where it is though.
506 
507     if (isNormalFlowOnly()) {
508         m_isPaginated = parent()->renderer()->hasColumns();
509         return;
510     }
511 
512     // If we're not normal flow, then we need to look for a multi-column object between us and our stacking context.
513     RenderLayer* ancestorStackingContext = stackingContext();
514     for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
515         if (curr->renderer()->hasColumns()) {
516             m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox());
517             return;
518         }
519         if (curr == ancestorStackingContext)
520             return;
521     }
522 }
523 
setHasVisibleContent(bool b)524 void RenderLayer::setHasVisibleContent(bool b)
525 {
526     if (m_hasVisibleContent == b && !m_visibleContentStatusDirty)
527         return;
528     m_visibleContentStatusDirty = false;
529     m_hasVisibleContent = b;
530     if (m_hasVisibleContent) {
531         RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
532         m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
533         m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer);
534         if (!isNormalFlowOnly()) {
535             for (RenderLayer* sc = stackingContext(); sc; sc = sc->stackingContext()) {
536                 sc->dirtyZOrderLists();
537                 if (sc->hasVisibleContent())
538                     break;
539             }
540         }
541     }
542     if (parent())
543         parent()->childVisibilityChanged(m_hasVisibleContent);
544 }
545 
dirtyVisibleContentStatus()546 void RenderLayer::dirtyVisibleContentStatus()
547 {
548     m_visibleContentStatusDirty = true;
549     if (parent())
550         parent()->dirtyVisibleDescendantStatus();
551 }
552 
childVisibilityChanged(bool newVisibility)553 void RenderLayer::childVisibilityChanged(bool newVisibility)
554 {
555     if (m_hasVisibleDescendant == newVisibility || m_visibleDescendantStatusDirty)
556         return;
557     if (newVisibility) {
558         RenderLayer* l = this;
559         while (l && !l->m_visibleDescendantStatusDirty && !l->m_hasVisibleDescendant) {
560             l->m_hasVisibleDescendant = true;
561             l = l->parent();
562         }
563     } else
564         dirtyVisibleDescendantStatus();
565 }
566 
dirtyVisibleDescendantStatus()567 void RenderLayer::dirtyVisibleDescendantStatus()
568 {
569     RenderLayer* l = this;
570     while (l && !l->m_visibleDescendantStatusDirty) {
571         l->m_visibleDescendantStatusDirty = true;
572         l = l->parent();
573     }
574 }
575 
updateVisibilityStatus()576 void RenderLayer::updateVisibilityStatus()
577 {
578     if (m_visibleDescendantStatusDirty) {
579         m_hasVisibleDescendant = false;
580         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
581             child->updateVisibilityStatus();
582             if (child->m_hasVisibleContent || child->m_hasVisibleDescendant) {
583                 m_hasVisibleDescendant = true;
584                 break;
585             }
586         }
587         m_visibleDescendantStatusDirty = false;
588     }
589 
590     if (m_visibleContentStatusDirty) {
591         if (renderer()->style()->visibility() == VISIBLE)
592             m_hasVisibleContent = true;
593         else {
594             // layer may be hidden but still have some visible content, check for this
595             m_hasVisibleContent = false;
596             RenderObject* r = renderer()->firstChild();
597             while (r) {
598                 if (r->style()->visibility() == VISIBLE && !r->hasLayer()) {
599                     m_hasVisibleContent = true;
600                     break;
601                 }
602                 if (r->firstChild() && !r->hasLayer())
603                     r = r->firstChild();
604                 else if (r->nextSibling())
605                     r = r->nextSibling();
606                 else {
607                     do {
608                         r = r->parent();
609                         if (r == renderer())
610                             r = 0;
611                     } while (r && !r->nextSibling());
612                     if (r)
613                         r = r->nextSibling();
614                 }
615             }
616         }
617         m_visibleContentStatusDirty = false;
618     }
619 }
620 
dirty3DTransformedDescendantStatus()621 void RenderLayer::dirty3DTransformedDescendantStatus()
622 {
623     RenderLayer* curr = stackingContext();
624     if (curr)
625         curr->m_3DTransformedDescendantStatusDirty = true;
626 
627     // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
628     // Note that preserves3D() creates stacking context, so we can just run up the stacking contexts.
629     while (curr && curr->preserves3D()) {
630         curr->m_3DTransformedDescendantStatusDirty = true;
631         curr = curr->stackingContext();
632     }
633 }
634 
635 // Return true if this layer or any preserve-3d descendants have 3d.
update3DTransformedDescendantStatus()636 bool RenderLayer::update3DTransformedDescendantStatus()
637 {
638     if (m_3DTransformedDescendantStatusDirty) {
639         m_has3DTransformedDescendant = false;
640 
641         // Transformed or preserve-3d descendants can only be in the z-order lists, not
642         // in the normal flow list, so we only need to check those.
643         if (m_posZOrderList) {
644             for (unsigned i = 0; i < m_posZOrderList->size(); ++i)
645                 m_has3DTransformedDescendant |= m_posZOrderList->at(i)->update3DTransformedDescendantStatus();
646         }
647 
648         // Now check our negative z-index children.
649         if (m_negZOrderList) {
650             for (unsigned i = 0; i < m_negZOrderList->size(); ++i)
651                 m_has3DTransformedDescendant |= m_negZOrderList->at(i)->update3DTransformedDescendantStatus();
652         }
653 
654         m_3DTransformedDescendantStatusDirty = false;
655     }
656 
657     // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
658     // the m_has3DTransformedDescendant set.
659     if (preserves3D())
660         return has3DTransform() || m_has3DTransformedDescendant;
661 
662     return has3DTransform();
663 }
664 
updateLayerPosition()665 void RenderLayer::updateLayerPosition()
666 {
667     IntPoint localPoint;
668     IntSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
669     if (renderer()->isRenderInline()) {
670         RenderInline* inlineFlow = toRenderInline(renderer());
671         IntRect lineBox = inlineFlow->linesBoundingBox();
672         setWidth(lineBox.width());
673         setHeight(lineBox.height());
674         inlineBoundingBoxOffset = IntSize(lineBox.x(), lineBox.y());
675         localPoint += inlineBoundingBoxOffset;
676     } else if (RenderBox* box = renderBox()) {
677         setWidth(box->width());
678         setHeight(box->height());
679         localPoint += box->locationOffsetIncludingFlipping();
680     }
681 
682     // Clear our cached clip rect information.
683     clearClipRects();
684 
685     if (!renderer()->isPositioned() && renderer()->parent()) {
686         // We must adjust our position by walking up the render tree looking for the
687         // nearest enclosing object with a layer.
688         RenderObject* curr = renderer()->parent();
689         while (curr && !curr->hasLayer()) {
690             if (curr->isBox() && !curr->isTableRow()) {
691                 // Rows and cells share the same coordinate space (that of the section).
692                 // Omit them when computing our xpos/ypos.
693                 localPoint += toRenderBox(curr)->locationOffsetIncludingFlipping();
694             }
695             curr = curr->parent();
696         }
697         if (curr->isBox() && curr->isTableRow()) {
698             // Put ourselves into the row coordinate space.
699             localPoint -= toRenderBox(curr)->locationOffsetIncludingFlipping();
700         }
701     }
702 
703     // Subtract our parent's scroll offset.
704     if (renderer()->isPositioned() && enclosingPositionedAncestor()) {
705         RenderLayer* positionedParent = enclosingPositionedAncestor();
706 
707         // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
708         IntSize offset = positionedParent->scrolledContentOffset();
709         localPoint -= offset;
710 
711         if (renderer()->isPositioned() && positionedParent->renderer()->isRelPositioned() && positionedParent->renderer()->isRenderInline()) {
712             IntSize offset = toRenderInline(positionedParent->renderer())->relativePositionedInlineOffset(toRenderBox(renderer()));
713             localPoint += offset;
714         }
715     } else if (parent()) {
716         if (isComposited()) {
717             // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
718             // They won't split across columns properly.
719             IntSize columnOffset;
720             parent()->renderer()->adjustForColumns(columnOffset, localPoint);
721             localPoint += columnOffset;
722         }
723 
724         IntSize scrollOffset = parent()->scrolledContentOffset();
725         localPoint -= scrollOffset;
726     }
727 
728     m_relX = m_relY = 0;
729     if (renderer()->isRelPositioned()) {
730         m_relX = renderer()->relativePositionOffsetX();
731         m_relY = renderer()->relativePositionOffsetY();
732         localPoint.move(m_relX, m_relY);
733     }
734 
735     // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
736     localPoint -= inlineBoundingBoxOffset;
737     setLocation(localPoint.x(), localPoint.y());
738 }
739 
perspectiveTransform() const740 TransformationMatrix RenderLayer::perspectiveTransform() const
741 {
742     if (!renderer()->hasTransform())
743         return TransformationMatrix();
744 
745     RenderStyle* style = renderer()->style();
746     if (!style->hasPerspective())
747         return TransformationMatrix();
748 
749     // Maybe fetch the perspective from the backing?
750     const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
751     const float boxWidth = borderBox.width();
752     const float boxHeight = borderBox.height();
753 
754     float perspectiveOriginX = style->perspectiveOriginX().calcFloatValue(boxWidth);
755     float perspectiveOriginY = style->perspectiveOriginY().calcFloatValue(boxHeight);
756 
757     // A perspective origin of 0,0 makes the vanishing point in the center of the element.
758     // We want it to be in the top-left, so subtract half the height and width.
759     perspectiveOriginX -= boxWidth / 2.0f;
760     perspectiveOriginY -= boxHeight / 2.0f;
761 
762     TransformationMatrix t;
763     t.translate(perspectiveOriginX, perspectiveOriginY);
764     t.applyPerspective(style->perspective());
765     t.translate(-perspectiveOriginX, -perspectiveOriginY);
766 
767     return t;
768 }
769 
perspectiveOrigin() const770 FloatPoint RenderLayer::perspectiveOrigin() const
771 {
772     if (!renderer()->hasTransform())
773         return FloatPoint();
774 
775     const IntRect borderBox = toRenderBox(renderer())->borderBoxRect();
776     RenderStyle* style = renderer()->style();
777 
778     return FloatPoint(style->perspectiveOriginX().calcFloatValue(borderBox.width()),
779                       style->perspectiveOriginY().calcFloatValue(borderBox.height()));
780 }
781 
stackingContext() const782 RenderLayer* RenderLayer::stackingContext() const
783 {
784     RenderLayer* layer = parent();
785     while (layer && !layer->renderer()->isRenderView() && !layer->renderer()->isRoot() && layer->renderer()->style()->hasAutoZIndex())
786         layer = layer->parent();
787     return layer;
788 }
789 
isPositionedContainer(RenderLayer * layer)790 static inline bool isPositionedContainer(RenderLayer* layer)
791 {
792     RenderObject* o = layer->renderer();
793     return o->isRenderView() || o->isPositioned() || o->isRelPositioned() || layer->hasTransform();
794 }
795 
isFixedPositionedContainer(RenderLayer * layer)796 static inline bool isFixedPositionedContainer(RenderLayer* layer)
797 {
798     RenderObject* o = layer->renderer();
799     return o->isRenderView() || layer->hasTransform();
800 }
801 
enclosingPositionedAncestor() const802 RenderLayer* RenderLayer::enclosingPositionedAncestor() const
803 {
804     RenderLayer* curr = parent();
805     while (curr && !isPositionedContainer(curr))
806         curr = curr->parent();
807 
808     return curr;
809 }
810 
enclosingTransformedAncestor() const811 RenderLayer* RenderLayer::enclosingTransformedAncestor() const
812 {
813     RenderLayer* curr = parent();
814     while (curr && !curr->renderer()->isRenderView() && !curr->transform())
815         curr = curr->parent();
816 
817     return curr;
818 }
819 
compositingContainer(const RenderLayer * layer)820 static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
821 {
822     return layer->isNormalFlowOnly() ? layer->parent() : layer->stackingContext();
823 }
824 
825 #if USE(ACCELERATED_COMPOSITING)
enclosingCompositingLayer(bool includeSelf) const826 RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
827 {
828     if (includeSelf && isComposited())
829         return const_cast<RenderLayer*>(this);
830 
831     for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
832         if (curr->isComposited())
833             return const_cast<RenderLayer*>(curr);
834     }
835 
836     return 0;
837 }
838 #endif
839 
clippingRoot() const840 RenderLayer* RenderLayer::clippingRoot() const
841 {
842 #if USE(ACCELERATED_COMPOSITING)
843     if (isComposited())
844         return const_cast<RenderLayer*>(this);
845 #endif
846 
847     const RenderLayer* current = this;
848     while (current) {
849         if (current->renderer()->isRenderView())
850             return const_cast<RenderLayer*>(current);
851 
852         current = compositingContainer(current);
853         ASSERT(current);
854         if (current->transform()
855 #if USE(ACCELERATED_COMPOSITING)
856             || current->isComposited()
857 #endif
858         )
859             return const_cast<RenderLayer*>(current);
860     }
861 
862     ASSERT_NOT_REACHED();
863     return 0;
864 }
865 
absoluteToContents(const IntPoint & absolutePoint) const866 IntPoint RenderLayer::absoluteToContents(const IntPoint& absolutePoint) const
867 {
868     // We don't use convertToLayerCoords because it doesn't know about transforms
869     return roundedIntPoint(renderer()->absoluteToLocal(absolutePoint, false, true));
870 }
871 
requiresSlowRepaints() const872 bool RenderLayer::requiresSlowRepaints() const
873 {
874     if (isTransparent() || hasReflection() || hasTransform())
875         return true;
876     if (!parent())
877         return false;
878     return parent()->requiresSlowRepaints();
879 }
880 
isTransparent() const881 bool RenderLayer::isTransparent() const
882 {
883 #if ENABLE(SVG)
884     if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
885         return false;
886 #endif
887     return renderer()->isTransparent() || renderer()->hasMask();
888 }
889 
transparentPaintingAncestor()890 RenderLayer* RenderLayer::transparentPaintingAncestor()
891 {
892     if (isComposited())
893         return 0;
894 
895     for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
896         if (curr->isComposited())
897             return 0;
898         if (curr->isTransparent())
899             return curr;
900     }
901     return 0;
902 }
903 
904 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior);
905 
expandClipRectForDescendantsAndReflection(IntRect & clipRect,const RenderLayer * l,const RenderLayer * rootLayer,PaintBehavior paintBehavior)906 static void expandClipRectForDescendantsAndReflection(IntRect& clipRect, const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
907 {
908     // If we have a mask, then the clip is limited to the border box area (and there is
909     // no need to examine child layers).
910     if (!l->renderer()->hasMask()) {
911         // Note: we don't have to walk z-order lists since transparent elements always establish
912         // a stacking context.  This means we can just walk the layer tree directly.
913         for (RenderLayer* curr = l->firstChild(); curr; curr = curr->nextSibling()) {
914             if (!l->reflection() || l->reflectionLayer() != curr)
915                 clipRect.unite(transparencyClipBox(curr, rootLayer, paintBehavior));
916         }
917     }
918 
919     // If we have a reflection, then we need to account for that when we push the clip.  Reflect our entire
920     // current transparencyClipBox to catch all child layers.
921     // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
922     // size into the parent layer.
923     if (l->renderer()->hasReflection()) {
924         int deltaX = 0;
925         int deltaY = 0;
926         l->convertToLayerCoords(rootLayer, deltaX, deltaY);
927         clipRect.move(-deltaX, -deltaY);
928         clipRect.unite(l->renderBox()->reflectedRect(clipRect));
929         clipRect.move(deltaX, deltaY);
930     }
931 }
932 
transparencyClipBox(const RenderLayer * l,const RenderLayer * rootLayer,PaintBehavior paintBehavior)933 static IntRect transparencyClipBox(const RenderLayer* l, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
934 {
935     // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
936     // paintDirtyRect, and that should cut down on the amount we have to paint.  Still it
937     // would be better to respect clips.
938 
939     if (rootLayer != l && l->paintsWithTransform(paintBehavior)) {
940         // The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
941         // the transformed layer and all of its children.
942         int x = 0;
943         int y = 0;
944         l->convertToLayerCoords(rootLayer, x, y);
945 
946         TransformationMatrix transform;
947         transform.translate(x, y);
948         transform = transform * *l->transform();
949 
950         IntRect clipRect = l->boundingBox(l);
951         expandClipRectForDescendantsAndReflection(clipRect, l, l, paintBehavior);
952         return transform.mapRect(clipRect);
953     }
954 
955     IntRect clipRect = l->boundingBox(rootLayer);
956     expandClipRectForDescendantsAndReflection(clipRect, l, rootLayer, paintBehavior);
957     return clipRect;
958 }
959 
beginTransparencyLayers(GraphicsContext * p,const RenderLayer * rootLayer,PaintBehavior paintBehavior)960 void RenderLayer::beginTransparencyLayers(GraphicsContext* p, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
961 {
962     if (p->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency))
963         return;
964 
965     RenderLayer* ancestor = transparentPaintingAncestor();
966     if (ancestor)
967         ancestor->beginTransparencyLayers(p, rootLayer, paintBehavior);
968 
969     if (paintsWithTransparency(paintBehavior)) {
970         m_usedTransparency = true;
971         p->save();
972         IntRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior);
973         p->clip(clipRect);
974         p->beginTransparencyLayer(renderer()->opacity());
975 #ifdef REVEAL_TRANSPARENCY_LAYERS
976         p->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), ColorSpaceDeviceRGB);
977         p->fillRect(clipRect);
978 #endif
979     }
980 }
981 
operator new(size_t sz,RenderArena * renderArena)982 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
983 {
984     return renderArena->allocate(sz);
985 }
986 
operator delete(void * ptr,size_t sz)987 void RenderLayer::operator delete(void* ptr, size_t sz)
988 {
989     // Stash size where destroy can find it.
990     *(size_t *)ptr = sz;
991 }
992 
destroy(RenderArena * renderArena)993 void RenderLayer::destroy(RenderArena* renderArena)
994 {
995     delete this;
996 
997     // Recover the size left there for us by operator delete and free the memory.
998     renderArena->free(*(size_t *)this, this);
999 }
1000 
addChild(RenderLayer * child,RenderLayer * beforeChild)1001 void RenderLayer::addChild(RenderLayer* child, RenderLayer* beforeChild)
1002 {
1003     RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
1004     if (prevSibling) {
1005         child->setPreviousSibling(prevSibling);
1006         prevSibling->setNextSibling(child);
1007         ASSERT(prevSibling != child);
1008     } else
1009         setFirstChild(child);
1010 
1011     if (beforeChild) {
1012         beforeChild->setPreviousSibling(child);
1013         child->setNextSibling(beforeChild);
1014         ASSERT(beforeChild != child);
1015     } else
1016         setLastChild(child);
1017 
1018     child->setParent(this);
1019 
1020     if (child->isNormalFlowOnly())
1021         dirtyNormalFlowList();
1022 
1023     if (!child->isNormalFlowOnly() || child->firstChild()) {
1024         // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
1025         // case where we're building up generated content layers.  This is ok, since the lists will start
1026         // off dirty in that case anyway.
1027         child->dirtyStackingContextZOrderLists();
1028     }
1029 
1030     child->updateVisibilityStatus();
1031     if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
1032         childVisibilityChanged(true);
1033 
1034 #if USE(ACCELERATED_COMPOSITING)
1035     compositor()->layerWasAdded(this, child);
1036 #endif
1037 }
1038 
removeChild(RenderLayer * oldChild)1039 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
1040 {
1041 #if USE(ACCELERATED_COMPOSITING)
1042     if (!renderer()->documentBeingDestroyed())
1043         compositor()->layerWillBeRemoved(this, oldChild);
1044 #endif
1045 
1046     // remove the child
1047     if (oldChild->previousSibling())
1048         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
1049     if (oldChild->nextSibling())
1050         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
1051 
1052     if (m_first == oldChild)
1053         m_first = oldChild->nextSibling();
1054     if (m_last == oldChild)
1055         m_last = oldChild->previousSibling();
1056 
1057     if (oldChild->isNormalFlowOnly())
1058         dirtyNormalFlowList();
1059     if (!oldChild->isNormalFlowOnly() || oldChild->firstChild()) {
1060         // Dirty the z-order list in which we are contained.  When called via the
1061         // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
1062         // from the main layer tree, so we need to null-check the |stackingContext| value.
1063         oldChild->dirtyStackingContextZOrderLists();
1064     }
1065 
1066     oldChild->setPreviousSibling(0);
1067     oldChild->setNextSibling(0);
1068     oldChild->setParent(0);
1069 
1070     oldChild->updateVisibilityStatus();
1071     if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
1072         childVisibilityChanged(false);
1073 
1074     return oldChild;
1075 }
1076 
removeOnlyThisLayer()1077 void RenderLayer::removeOnlyThisLayer()
1078 {
1079     if (!m_parent)
1080         return;
1081 
1082     // Mark that we are about to lose our layer. This makes render tree
1083     // walks ignore this layer while we're removing it.
1084     m_renderer->setHasLayer(false);
1085 
1086 #if USE(ACCELERATED_COMPOSITING)
1087     compositor()->layerWillBeRemoved(m_parent, this);
1088 #endif
1089 
1090     // Dirty the clip rects.
1091     clearClipRectsIncludingDescendants();
1092 
1093     // Remove us from the parent.
1094     RenderLayer* parent = m_parent;
1095     RenderLayer* nextSib = nextSibling();
1096     parent->removeChild(this);
1097 
1098     if (reflection())
1099         removeChild(reflectionLayer());
1100 
1101     // Now walk our kids and reattach them to our parent.
1102     RenderLayer* current = m_first;
1103     while (current) {
1104         RenderLayer* next = current->nextSibling();
1105         removeChild(current);
1106         parent->addChild(current, nextSib);
1107         current->setNeedsFullRepaint();
1108         current->updateLayerPositions(); // Depends on hasLayer() already being false for proper layout.
1109         current = next;
1110     }
1111 
1112     m_renderer->destroyLayer();
1113 }
1114 
insertOnlyThisLayer()1115 void RenderLayer::insertOnlyThisLayer()
1116 {
1117     if (!m_parent && renderer()->parent()) {
1118         // We need to connect ourselves when our renderer() has a parent.
1119         // Find our enclosingLayer and add ourselves.
1120         RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
1121         ASSERT(parentLayer);
1122         RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
1123         parentLayer->addChild(this, beforeChild);
1124     }
1125 
1126     // Remove all descendant layers from the hierarchy and add them to the new position.
1127     for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
1128         curr->moveLayers(m_parent, this);
1129 
1130     // Clear out all the clip rects.
1131     clearClipRectsIncludingDescendants();
1132 }
1133 
1134 void
convertToLayerCoords(const RenderLayer * ancestorLayer,int & xPos,int & yPos) const1135 RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& xPos, int& yPos) const
1136 {
1137     if (ancestorLayer == this)
1138         return;
1139 
1140     EPosition position = renderer()->style()->position();
1141     if (position == FixedPosition && (!ancestorLayer || ancestorLayer == renderer()->view()->layer())) {
1142         // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
1143         // localToAbsolute() on the RenderView.
1144         FloatPoint absPos = renderer()->localToAbsolute(FloatPoint(), true);
1145         xPos += absPos.x();
1146         yPos += absPos.y();
1147         return;
1148     }
1149 
1150     if (position == FixedPosition) {
1151         // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
1152         // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
1153         // so we should always find the ancestor at or before we find the fixed position container.
1154         RenderLayer* fixedPositionContainerLayer = 0;
1155         bool foundAncestor = false;
1156         for (RenderLayer* currLayer = parent(); currLayer; currLayer = currLayer->parent()) {
1157             if (currLayer == ancestorLayer)
1158                 foundAncestor = true;
1159 
1160             if (isFixedPositionedContainer(currLayer)) {
1161                 fixedPositionContainerLayer = currLayer;
1162                 ASSERT_UNUSED(foundAncestor, foundAncestor);
1163                 break;
1164             }
1165         }
1166 
1167         ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
1168 
1169         if (fixedPositionContainerLayer != ancestorLayer) {
1170             int fixedContainerX = 0;
1171             int fixedContainerY = 0;
1172             convertToLayerCoords(fixedPositionContainerLayer, fixedContainerX, fixedContainerY);
1173 
1174             int ancestorX = 0;
1175             int ancestorY = 0;
1176             ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorX, ancestorY);
1177 
1178             xPos += (fixedContainerX - ancestorX);
1179             yPos += (fixedContainerY - ancestorY);
1180             return;
1181         }
1182     }
1183 
1184     RenderLayer* parentLayer;
1185     if (position == AbsolutePosition || position == FixedPosition) {
1186         // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
1187         parentLayer = parent();
1188         bool foundAncestorFirst = false;
1189         while (parentLayer) {
1190             if (isPositionedContainer(parentLayer))
1191                 break;
1192 
1193             if (parentLayer == ancestorLayer) {
1194                 foundAncestorFirst = true;
1195                 break;
1196             }
1197 
1198             parentLayer = parentLayer->parent();
1199         }
1200 
1201         if (foundAncestorFirst) {
1202             // Found ancestorLayer before the abs. positioned container, so compute offset of both relative
1203             // to enclosingPositionedAncestor and subtract.
1204             RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
1205 
1206             int thisX = 0;
1207             int thisY = 0;
1208             convertToLayerCoords(positionedAncestor, thisX, thisY);
1209 
1210             int ancestorX = 0;
1211             int ancestorY = 0;
1212             ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorX, ancestorY);
1213 
1214             xPos += (thisX - ancestorX);
1215             yPos += (thisY - ancestorY);
1216             return;
1217         }
1218     } else
1219         parentLayer = parent();
1220 
1221     if (!parentLayer)
1222         return;
1223 
1224     parentLayer->convertToLayerCoords(ancestorLayer, xPos, yPos);
1225 
1226     xPos += x();
1227     yPos += y();
1228 }
1229 
adjustedScrollDelta(int beginningDelta)1230 static inline int adjustedScrollDelta(int beginningDelta) {
1231     // This implemention matches Firefox's.
1232     // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
1233     const int speedReducer = 12;
1234 
1235     int adjustedDelta = beginningDelta / speedReducer;
1236     if (adjustedDelta > 1)
1237         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1;
1238     else if (adjustedDelta < -1)
1239         adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1;
1240 
1241     return adjustedDelta;
1242 }
1243 
panScrollFromPoint(const IntPoint & sourcePoint)1244 void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
1245 {
1246     Frame* frame = renderer()->frame();
1247     if (!frame)
1248         return;
1249 
1250     IntPoint currentMousePosition = frame->eventHandler()->currentMousePosition();
1251 
1252     // 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
1253     static IntPoint previousMousePosition;
1254     if (currentMousePosition.x() < 0 || currentMousePosition.y() < 0)
1255         currentMousePosition = previousMousePosition;
1256     else
1257         previousMousePosition = currentMousePosition;
1258 
1259     int xDelta = currentMousePosition.x() - sourcePoint.x();
1260     int yDelta = currentMousePosition.y() - sourcePoint.y();
1261 
1262     if (abs(xDelta) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon
1263         xDelta = 0;
1264     if (abs(yDelta) <= ScrollView::noPanScrollRadius)
1265         yDelta = 0;
1266 
1267     scrollByRecursively(adjustedScrollDelta(xDelta), adjustedScrollDelta(yDelta));
1268 }
1269 
scrollByRecursively(int xDelta,int yDelta)1270 void RenderLayer::scrollByRecursively(int xDelta, int yDelta)
1271 {
1272     if (!xDelta && !yDelta)
1273         return;
1274 
1275     bool restrictedByLineClamp = false;
1276     if (renderer()->parent())
1277         restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1278 
1279     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1280         int newOffsetX = scrollXOffset() + xDelta;
1281         int newOffsetY = scrollYOffset() + yDelta;
1282         scrollToOffset(newOffsetX, newOffsetY);
1283 
1284         // If this layer can't do the scroll we ask the next layer up that can scroll to try
1285         int leftToScrollX = newOffsetX - scrollXOffset();
1286         int leftToScrollY = newOffsetY - scrollYOffset();
1287         if ((leftToScrollX || leftToScrollY) && renderer()->parent()) {
1288             RenderObject* nextRenderer = renderer()->parent();
1289             while (nextRenderer) {
1290                 if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea()) {
1291                     nextRenderer->enclosingLayer()->scrollByRecursively(leftToScrollX, leftToScrollY);
1292                     break;
1293                 }
1294                 nextRenderer = nextRenderer->parent();
1295             }
1296 
1297             Frame* frame = renderer()->frame();
1298             if (frame)
1299                 frame->eventHandler()->updateAutoscrollRenderer();
1300         }
1301     } else if (renderer()->view()->frameView()) {
1302         // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't
1303         // have an overflow clip. Which means that it is a document node that can be scrolled.
1304         renderer()->view()->frameView()->scrollBy(IntSize(xDelta, yDelta));
1305         // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement?
1306         // https://bugs.webkit.org/show_bug.cgi?id=28237
1307     }
1308 }
1309 
scrollToOffset(int x,int y)1310 void RenderLayer::scrollToOffset(int x, int y)
1311 {
1312     ScrollableArea::scrollToOffsetWithoutAnimation(IntPoint(x, y));
1313 }
1314 
scrollTo(int x,int y)1315 void RenderLayer::scrollTo(int x, int y)
1316 {
1317     RenderBox* box = renderBox();
1318     if (!box)
1319         return;
1320 
1321     if (box->style()->overflowX() != OMARQUEE) {
1322         if (x < 0)
1323             x = 0;
1324         if (y < 0)
1325             y = 0;
1326 
1327         // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
1328         // to be (for overflow:hidden blocks).
1329         int maxX = scrollWidth() - box->clientWidth();
1330         if (maxX < 0)
1331             maxX = 0;
1332         int maxY = scrollHeight() - box->clientHeight();
1333         if (maxY < 0)
1334             maxY = 0;
1335 
1336         if (x > maxX)
1337             x = maxX;
1338         if (y > maxY)
1339             y = maxY;
1340     }
1341 
1342     // FIXME: Eventually, we will want to perform a blit.  For now never
1343     // blit, since the check for blitting is going to be very
1344     // complicated (since it will involve testing whether our layer
1345     // is either occluded by another layer or clipped by an enclosing
1346     // layer or contains fixed backgrounds, etc.).
1347     int newScrollX = x - m_scrollOrigin.x();
1348     int newScrollY = y - m_scrollOrigin.y();
1349     if (m_scrollY == newScrollY && m_scrollX == newScrollX)
1350         return;
1351     m_scrollX = newScrollX;
1352     m_scrollY = newScrollY;
1353 
1354     // Update the positions of our child layers. Don't have updateLayerPositions() update
1355     // compositing layers, because we need to do a deep update from the compositing ancestor.
1356     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
1357         child->updateLayerPositions(0);
1358 
1359     RenderView* view = renderer()->view();
1360 
1361     // We should have a RenderView if we're trying to scroll.
1362     ASSERT(view);
1363     if (view) {
1364 #if ENABLE(DASHBOARD_SUPPORT)
1365         // Update dashboard regions, scrolling may change the clip of a
1366         // particular region.
1367         view->frameView()->updateDashboardRegions();
1368 #endif
1369 
1370         view->updateWidgetPositions();
1371     }
1372 
1373 #if USE(ACCELERATED_COMPOSITING)
1374     if (compositor()->inCompositingMode()) {
1375         // Our stacking context is guaranteed to contain all of our descendants that may need
1376         // repositioning, so update compositing layers from there.
1377         if (RenderLayer* compositingAncestor = stackingContext()->enclosingCompositingLayer()) {
1378             if (compositor()->compositingConsultsOverlap())
1379                 compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor);
1380             else {
1381                 bool isUpdateRoot = true;
1382                 compositingAncestor->backing()->updateAfterLayout(RenderLayerBacking::AllDescendants, isUpdateRoot);
1383             }
1384         }
1385     }
1386 #endif
1387 
1388     RenderBoxModelObject* repaintContainer = renderer()->containerForRepaint();
1389     IntRect rectForRepaint = renderer()->clippedOverflowRectForRepaint(repaintContainer);
1390 
1391     Frame* frame = renderer()->frame();
1392     if (frame) {
1393         // The caret rect needs to be invalidated after scrolling
1394         frame->selection()->setCaretRectNeedsUpdate();
1395 
1396         FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint);
1397         if (repaintContainer)
1398             quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
1399         frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
1400     }
1401 
1402     // Just schedule a full repaint of our object.
1403     if (view)
1404         renderer()->repaintUsingContainer(repaintContainer, rectForRepaint);
1405 
1406     // Schedule the scroll DOM event.
1407     renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), EventQueue::ScrollEventElementTarget);
1408 }
1409 
scrollRectToVisible(const IntRect & rect,bool scrollToAnchor,const ScrollAlignment & alignX,const ScrollAlignment & alignY)1410 void RenderLayer::scrollRectToVisible(const IntRect& rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1411 {
1412     RenderLayer* parentLayer = 0;
1413     IntRect newRect = rect;
1414     int xOffset = 0, yOffset = 0;
1415 
1416     // We may end up propagating a scroll event. It is important that we suspend events until
1417     // the end of the function since they could delete the layer or the layer's renderer().
1418     FrameView* frameView = renderer()->document()->view();
1419     if (frameView)
1420         frameView->pauseScheduledEvents();
1421 
1422     bool restrictedByLineClamp = false;
1423     if (renderer()->parent()) {
1424         parentLayer = renderer()->parent()->enclosingLayer();
1425         restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
1426     }
1427 
1428     if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
1429         // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.
1430         // This will prevent us from revealing text hidden by the slider in Safari RSS.
1431         RenderBox* box = renderBox();
1432         ASSERT(box);
1433         FloatPoint absPos = box->localToAbsolute();
1434         absPos.move(box->borderLeft(), box->borderTop());
1435 
1436         IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight());
1437         IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());
1438         IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);
1439 
1440         xOffset = r.x() - absPos.x();
1441         yOffset = r.y() - absPos.y();
1442         // Adjust offsets if they're outside of the allowable range.
1443         xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));
1444         yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));
1445 
1446         if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {
1447             int diffX = scrollXOffset();
1448             int diffY = scrollYOffset();
1449             scrollToOffset(xOffset, yOffset);
1450             diffX = scrollXOffset() - diffX;
1451             diffY = scrollYOffset() - diffY;
1452             newRect.setX(rect.x() - diffX);
1453             newRect.setY(rect.y() - diffY);
1454         }
1455     } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) {
1456         if (frameView) {
1457             if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) {
1458                 IntRect viewRect = frameView->visibleContentRect();
1459                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
1460 
1461                 xOffset = r.x();
1462                 yOffset = r.y();
1463                 // Adjust offsets if they're outside of the allowable range.
1464                 xOffset = max(0, min(frameView->contentsWidth(), xOffset));
1465                 yOffset = max(0, min(frameView->contentsHeight(), yOffset));
1466 
1467                 frameView->setScrollPosition(IntPoint(xOffset, yOffset));
1468                 parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer();
1469                 newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
1470                 newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
1471             } else {
1472                 IntRect viewRect = frameView->visibleContentRect();
1473                 IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);
1474 
1475                 frameView->setScrollPosition(r.location());
1476 
1477                 // This is the outermost view of a web page, so after scrolling this view we
1478                 // scroll its container by calling Page::scrollRectIntoView.
1479                 // This only has an effect on the Mac platform in applications
1480                 // that put web views into scrolling containers, such as Mac OS X Mail.
1481                 // The canAutoscroll function in EventHandler also knows about this.
1482                 if (Frame* frame = frameView->frame()) {
1483                     if (Page* page = frame->page())
1484                         page->chrome()->scrollRectIntoView(rect);
1485                 }
1486             }
1487         }
1488     }
1489 
1490     if (parentLayer)
1491         parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY);
1492 
1493     if (frameView)
1494         frameView->resumeScheduledEvents();
1495 }
1496 
getRectToExpose(const IntRect & visibleRect,const IntRect & exposeRect,const ScrollAlignment & alignX,const ScrollAlignment & alignY)1497 IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
1498 {
1499     // Determine the appropriate X behavior.
1500     ScrollBehavior scrollX;
1501     IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
1502     int intersectWidth = intersection(visibleRect, exposeRectX).width();
1503     if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
1504         // If the rectangle is fully visible, use the specified visible behavior.
1505         // If the rectangle is partially visible, but over a certain threshold,
1506         // then treat it as fully visible to avoid unnecessary horizontal scrolling
1507         scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1508     else if (intersectWidth == visibleRect.width()) {
1509         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1510         scrollX = ScrollAlignment::getVisibleBehavior(alignX);
1511         if (scrollX == alignCenter)
1512             scrollX = noScroll;
1513     } else if (intersectWidth > 0)
1514         // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
1515         scrollX = ScrollAlignment::getPartialBehavior(alignX);
1516     else
1517         scrollX = ScrollAlignment::getHiddenBehavior(alignX);
1518     // If we're trying to align to the closest edge, and the exposeRect is further right
1519     // than the visibleRect, and not bigger than the visible area, then align with the right.
1520     if (scrollX == alignToClosestEdge && exposeRect.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width())
1521         scrollX = alignRight;
1522 
1523     // Given the X behavior, compute the X coordinate.
1524     int x;
1525     if (scrollX == noScroll)
1526         x = visibleRect.x();
1527     else if (scrollX == alignRight)
1528         x = exposeRect.maxX() - visibleRect.width();
1529     else if (scrollX == alignCenter)
1530         x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;
1531     else
1532         x = exposeRect.x();
1533 
1534     // Determine the appropriate Y behavior.
1535     ScrollBehavior scrollY;
1536     IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
1537     int intersectHeight = intersection(visibleRect, exposeRectY).height();
1538     if (intersectHeight == exposeRect.height())
1539         // If the rectangle is fully visible, use the specified visible behavior.
1540         scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1541     else if (intersectHeight == visibleRect.height()) {
1542         // If the rect is bigger than the visible area, don't bother trying to center. Other alignments will work.
1543         scrollY = ScrollAlignment::getVisibleBehavior(alignY);
1544         if (scrollY == alignCenter)
1545             scrollY = noScroll;
1546     } else if (intersectHeight > 0)
1547         // If the rectangle is partially visible, use the specified partial behavior
1548         scrollY = ScrollAlignment::getPartialBehavior(alignY);
1549     else
1550         scrollY = ScrollAlignment::getHiddenBehavior(alignY);
1551     // If we're trying to align to the closest edge, and the exposeRect is further down
1552     // than the visibleRect, and not bigger than the visible area, then align with the bottom.
1553     if (scrollY == alignToClosestEdge && exposeRect.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height())
1554         scrollY = alignBottom;
1555 
1556     // Given the Y behavior, compute the Y coordinate.
1557     int y;
1558     if (scrollY == noScroll)
1559         y = visibleRect.y();
1560     else if (scrollY == alignBottom)
1561         y = exposeRect.maxY() - visibleRect.height();
1562     else if (scrollY == alignCenter)
1563         y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
1564     else
1565         y = exposeRect.y();
1566 
1567     return IntRect(IntPoint(x, y), visibleRect.size());
1568 }
1569 
autoscroll()1570 void RenderLayer::autoscroll()
1571 {
1572     Frame* frame = renderer()->frame();
1573     if (!frame)
1574         return;
1575 
1576     FrameView* frameView = frame->view();
1577     if (!frameView)
1578         return;
1579 
1580 #if ENABLE(DRAG_SUPPORT)
1581     frame->eventHandler()->updateSelectionForMouseDrag();
1582 #endif
1583 
1584     IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());
1585     scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
1586 }
1587 
resize(const PlatformMouseEvent & evt,const IntSize & oldOffset)1588 void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset)
1589 {
1590     // FIXME: This should be possible on generated content but is not right now.
1591     if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node())
1592         return;
1593 
1594     // Set the width and height of the shadow ancestor node if there is one.
1595     // This is necessary for textarea elements since the resizable layer is in the shadow content.
1596     Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode());
1597     RenderBox* renderer = toRenderBox(element->renderer());
1598 
1599     EResize resize = renderer->style()->resize();
1600     if (resize == RESIZE_NONE)
1601         return;
1602 
1603     Document* document = element->document();
1604     if (!document->frame()->eventHandler()->mousePressed())
1605         return;
1606 
1607     float zoomFactor = renderer->style()->effectiveZoom();
1608 
1609     IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos()));
1610     newOffset.setWidth(newOffset.width() / zoomFactor);
1611     newOffset.setHeight(newOffset.height() / zoomFactor);
1612 
1613     IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);
1614     IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
1615     element->setMinimumSizeForResizing(minimumSize);
1616 
1617     IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
1618 
1619     IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
1620 
1621     CSSStyleDeclaration* style = element->style();
1622     bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
1623 
1624     ExceptionCode ec;
1625 
1626     if (resize != RESIZE_VERTICAL && difference.width()) {
1627         if (element->isFormControlElement()) {
1628             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1629             style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);
1630             style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec);
1631         }
1632         int baseWidth = renderer->width() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingWidth());
1633         baseWidth = baseWidth / zoomFactor;
1634         style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);
1635     }
1636 
1637     if (resize != RESIZE_HORIZONTAL && difference.height()) {
1638         if (element->isFormControlElement()) {
1639             // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
1640             style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);
1641             style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec);
1642         }
1643         int baseHeight = renderer->height() - (isBoxSizingBorder ? 0 : renderer->borderAndPaddingHeight());
1644         baseHeight = baseHeight / zoomFactor;
1645         style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec);
1646     }
1647 
1648     document->updateLayout();
1649 
1650     // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
1651 }
1652 
scrollSize(ScrollbarOrientation orientation) const1653 int RenderLayer::scrollSize(ScrollbarOrientation orientation) const
1654 {
1655     Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_hBar : m_vBar).get();
1656     return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
1657 }
1658 
setScrollOffset(const IntPoint & offset)1659 void RenderLayer::setScrollOffset(const IntPoint& offset)
1660 {
1661     scrollTo(offset.x(), offset.y());
1662 }
1663 
scrollPosition(Scrollbar * scrollbar) const1664 int RenderLayer::scrollPosition(Scrollbar* scrollbar) const
1665 {
1666     if (scrollbar->orientation() == HorizontalScrollbar)
1667         return scrollXOffset();
1668     if (scrollbar->orientation() == VerticalScrollbar)
1669         return scrollYOffset();
1670     return 0;
1671 }
1672 
isActive() const1673 bool RenderLayer::isActive() const
1674 {
1675     Page* page = renderer()->frame()->page();
1676     return page && page->focusController()->isActive();
1677 }
1678 
cornerRect(const RenderLayer * layer,const IntRect & bounds)1679 static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds)
1680 {
1681     int horizontalThickness;
1682     int verticalThickness;
1683     if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1684         // FIXME: This isn't right.  We need to know the thickness of custom scrollbars
1685         // even when they don't exist in order to set the resizer square size properly.
1686         horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();
1687         verticalThickness = horizontalThickness;
1688     } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) {
1689         horizontalThickness = layer->verticalScrollbar()->width();
1690         verticalThickness = horizontalThickness;
1691     } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) {
1692         verticalThickness = layer->horizontalScrollbar()->height();
1693         horizontalThickness = verticalThickness;
1694     } else {
1695         horizontalThickness = layer->verticalScrollbar()->width();
1696         verticalThickness = layer->horizontalScrollbar()->height();
1697     }
1698     return IntRect(bounds.maxX() - horizontalThickness - layer->renderer()->style()->borderRightWidth(),
1699                    bounds.maxY() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),
1700                    horizontalThickness, verticalThickness);
1701 }
1702 
scrollCornerRect() const1703 IntRect RenderLayer::scrollCornerRect() const
1704 {
1705     // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
1706     // This happens when:
1707     // (a) A resizer is present and at least one scrollbar is present
1708     // (b) Both scrollbars are present.
1709     bool hasHorizontalBar = horizontalScrollbar();
1710     bool hasVerticalBar = verticalScrollbar();
1711     bool hasResizer = renderer()->style()->resize() != RESIZE_NONE;
1712     if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
1713         return cornerRect(this, renderBox()->borderBoxRect());
1714     return IntRect();
1715 }
1716 
resizerCornerRect(const RenderLayer * layer,const IntRect & bounds)1717 static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
1718 {
1719     ASSERT(layer->renderer()->isBox());
1720     if (layer->renderer()->style()->resize() == RESIZE_NONE)
1721         return IntRect();
1722     return cornerRect(layer, bounds);
1723 }
1724 
scrollCornerAndResizerRect() const1725 IntRect RenderLayer::scrollCornerAndResizerRect() const
1726 {
1727     RenderBox* box = renderBox();
1728     if (!box)
1729         return IntRect();
1730     IntRect scrollCornerAndResizer = scrollCornerRect();
1731     if (scrollCornerAndResizer.isEmpty())
1732         scrollCornerAndResizer = resizerCornerRect(this, box->borderBoxRect());
1733     return scrollCornerAndResizer;
1734 }
1735 
isScrollCornerVisible() const1736 bool RenderLayer::isScrollCornerVisible() const
1737 {
1738     ASSERT(renderer()->isBox());
1739     return !scrollCornerRect().isEmpty();
1740 }
1741 
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntRect & scrollbarRect) const1742 IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
1743 {
1744     RenderView* view = renderer()->view();
1745     if (!view)
1746         return scrollbarRect;
1747 
1748     IntRect rect = scrollbarRect;
1749     rect.move(scrollbarOffset(scrollbar));
1750 
1751     return view->frameView()->convertFromRenderer(renderer(), rect);
1752 }
1753 
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntRect & parentRect) const1754 IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
1755 {
1756     RenderView* view = renderer()->view();
1757     if (!view)
1758         return parentRect;
1759 
1760     IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect);
1761     rect.move(-scrollbarOffset(scrollbar));
1762     return rect;
1763 }
1764 
convertFromScrollbarToContainingView(const Scrollbar * scrollbar,const IntPoint & scrollbarPoint) const1765 IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
1766 {
1767     RenderView* view = renderer()->view();
1768     if (!view)
1769         return scrollbarPoint;
1770 
1771     IntPoint point = scrollbarPoint;
1772     point.move(scrollbarOffset(scrollbar));
1773     return view->frameView()->convertFromRenderer(renderer(), point);
1774 }
1775 
convertFromContainingViewToScrollbar(const Scrollbar * scrollbar,const IntPoint & parentPoint) const1776 IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
1777 {
1778     RenderView* view = renderer()->view();
1779     if (!view)
1780         return parentPoint;
1781 
1782     IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint);
1783 
1784     point.move(-scrollbarOffset(scrollbar));
1785     return point;
1786 }
1787 
contentsSize() const1788 IntSize RenderLayer::contentsSize() const
1789 {
1790     return IntSize(const_cast<RenderLayer*>(this)->scrollWidth(), const_cast<RenderLayer*>(this)->scrollHeight());
1791 }
1792 
visibleHeight() const1793 int RenderLayer::visibleHeight() const
1794 {
1795     return m_height;
1796 }
1797 
visibleWidth() const1798 int RenderLayer::visibleWidth() const
1799 {
1800     return m_width;
1801 }
1802 
shouldSuspendScrollAnimations() const1803 bool RenderLayer::shouldSuspendScrollAnimations() const
1804 {
1805     RenderView* view = renderer()->view();
1806     if (!view)
1807         return true;
1808     return view->frameView()->shouldSuspendScrollAnimations();
1809 }
1810 
currentMousePosition() const1811 IntPoint RenderLayer::currentMousePosition() const
1812 {
1813     return renderer()->frame() ? renderer()->frame()->eventHandler()->currentMousePosition() : IntPoint();
1814 }
1815 
scrollbarOffset(const Scrollbar * scrollbar) const1816 IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
1817 {
1818     RenderBox* box = renderBox();
1819 
1820     if (scrollbar == m_vBar.get())
1821         return IntSize(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
1822 
1823     if (scrollbar == m_hBar.get())
1824         return IntSize(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
1825 
1826     ASSERT_NOT_REACHED();
1827     return IntSize();
1828 }
1829 
invalidateScrollbarRect(Scrollbar * scrollbar,const IntRect & rect)1830 void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
1831 {
1832 #if USE(ACCELERATED_COMPOSITING)
1833     if (scrollbar == m_vBar.get()) {
1834         if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
1835             layer->setNeedsDisplayInRect(rect);
1836             return;
1837         }
1838     } else {
1839         if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
1840             layer->setNeedsDisplayInRect(rect);
1841             return;
1842         }
1843     }
1844 #endif
1845     IntRect scrollRect = rect;
1846     RenderBox* box = renderBox();
1847     ASSERT(box);
1848     if (scrollbar == m_vBar.get())
1849         scrollRect.move(box->width() - box->borderRight() - scrollbar->width(), box->borderTop());
1850     else
1851         scrollRect.move(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());
1852     renderer()->repaintRectangle(scrollRect);
1853 }
1854 
invalidateScrollCornerRect(const IntRect & rect)1855 void RenderLayer::invalidateScrollCornerRect(const IntRect& rect)
1856 {
1857 #if USE(ACCELERATED_COMPOSITING)
1858     if (GraphicsLayer* layer = layerForScrollCorner()) {
1859         layer->setNeedsDisplayInRect(rect);
1860         return;
1861     }
1862 #endif
1863     if (m_scrollCorner)
1864         m_scrollCorner->repaintRectangle(rect);
1865     if (m_resizer)
1866         m_resizer->repaintRectangle(rect);
1867 }
1868 
createScrollbar(ScrollbarOrientation orientation)1869 PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
1870 {
1871     RefPtr<Scrollbar> widget;
1872     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
1873     bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);
1874     if (hasCustomScrollbarStyle)
1875         widget = RenderScrollbar::createCustomScrollbar(this, orientation, toRenderBox(actualRenderer));
1876     else {
1877         widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
1878         if (orientation == HorizontalScrollbar)
1879             didAddHorizontalScrollbar(widget.get());
1880         else
1881             didAddVerticalScrollbar(widget.get());
1882     }
1883     renderer()->document()->view()->addChild(widget.get());
1884     return widget.release();
1885 }
1886 
destroyScrollbar(ScrollbarOrientation orientation)1887 void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
1888 {
1889     RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
1890     if (scrollbar) {
1891         if (scrollbar->isCustomScrollbar())
1892             static_cast<RenderScrollbar*>(scrollbar.get())->clearOwningRenderer();
1893         else {
1894             if (orientation == HorizontalScrollbar)
1895                 willRemoveHorizontalScrollbar(scrollbar.get());
1896             else
1897                 willRemoveVerticalScrollbar(scrollbar.get());
1898         }
1899 
1900         scrollbar->removeFromParent();
1901         scrollbar->disconnectFromScrollableArea();
1902         scrollbar = 0;
1903     }
1904 }
1905 
setHasHorizontalScrollbar(bool hasScrollbar)1906 void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
1907 {
1908     if (hasScrollbar == (m_hBar != 0))
1909         return;
1910 
1911     if (hasScrollbar)
1912         m_hBar = createScrollbar(HorizontalScrollbar);
1913     else
1914         destroyScrollbar(HorizontalScrollbar);
1915 
1916     // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1917     if (m_hBar)
1918         m_hBar->styleChanged();
1919     if (m_vBar)
1920         m_vBar->styleChanged();
1921 
1922 #if ENABLE(DASHBOARD_SUPPORT)
1923     // Force an update since we know the scrollbars have changed things.
1924     if (renderer()->document()->hasDashboardRegions())
1925         renderer()->document()->setDashboardRegionsDirty(true);
1926 #endif
1927 }
1928 
setHasVerticalScrollbar(bool hasScrollbar)1929 void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
1930 {
1931     if (hasScrollbar == (m_vBar != 0))
1932         return;
1933 
1934     if (hasScrollbar)
1935         m_vBar = createScrollbar(VerticalScrollbar);
1936     else
1937         destroyScrollbar(VerticalScrollbar);
1938 
1939      // Destroying or creating one bar can cause our scrollbar corner to come and go.  We need to update the opposite scrollbar's style.
1940     if (m_hBar)
1941         m_hBar->styleChanged();
1942     if (m_vBar)
1943         m_vBar->styleChanged();
1944 
1945 #if ENABLE(DASHBOARD_SUPPORT)
1946     // Force an update since we know the scrollbars have changed things.
1947     if (renderer()->document()->hasDashboardRegions())
1948         renderer()->document()->setDashboardRegionsDirty(true);
1949 #endif
1950 }
1951 
verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const1952 int RenderLayer::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const
1953 {
1954     if (!m_vBar || (m_vBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize))
1955         return 0;
1956     return m_vBar->width();
1957 }
1958 
horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const1959 int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const
1960 {
1961     if (!m_hBar || (m_hBar->isOverlayScrollbar() && relevancy == IgnoreOverlayScrollbarSize))
1962         return 0;
1963     return m_hBar->height();
1964 }
1965 
offsetFromResizeCorner(const IntPoint & absolutePoint) const1966 IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
1967 {
1968     // Currently the resize corner is always the bottom right corner
1969     IntPoint bottomRight(width(), height());
1970     IntPoint localPoint = absoluteToContents(absolutePoint);
1971     return localPoint - bottomRight;
1972 }
1973 
hasOverflowControls() const1974 bool RenderLayer::hasOverflowControls() const
1975 {
1976     return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE;
1977 }
1978 
positionOverflowControls(int tx,int ty)1979 void RenderLayer::positionOverflowControls(int tx, int ty)
1980 {
1981     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
1982         return;
1983 
1984     RenderBox* box = renderBox();
1985     if (!box)
1986         return;
1987 
1988     const IntRect& borderBox = box->borderBoxRect();
1989     const IntRect& scrollCorner = scrollCornerRect();
1990     IntRect absBounds(borderBox.x() + tx, borderBox.y() + ty, borderBox.width(), borderBox.height());
1991     if (m_vBar)
1992         m_vBar->setFrameRect(IntRect(absBounds.maxX() - box->borderRight() - m_vBar->width(),
1993                                      absBounds.y() + box->borderTop(),
1994                                      m_vBar->width(),
1995                                      absBounds.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height()));
1996 
1997     if (m_hBar)
1998         m_hBar->setFrameRect(IntRect(absBounds.x() + box->borderLeft(),
1999                                      absBounds.maxY() - box->borderBottom() - m_hBar->height(),
2000                                      absBounds.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
2001                                      m_hBar->height()));
2002 
2003 #if USE(ACCELERATED_COMPOSITING)
2004     if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
2005         if (m_hBar) {
2006             layer->setPosition(IntPoint(m_hBar->frameRect().x() - tx, m_hBar->frameRect().y() - ty));
2007             layer->setSize(m_hBar->frameRect().size());
2008         }
2009         layer->setDrawsContent(m_hBar);
2010     }
2011     if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
2012         if (m_vBar) {
2013             layer->setPosition(IntPoint(m_vBar->frameRect().x() - tx, m_vBar->frameRect().y() - ty));
2014             layer->setSize(m_vBar->frameRect().size());
2015         }
2016         layer->setDrawsContent(m_vBar);
2017     }
2018 
2019     if (GraphicsLayer* layer = layerForScrollCorner()) {
2020         const IntRect& scrollCornerAndResizer = scrollCornerAndResizerRect();
2021         layer->setPosition(scrollCornerAndResizer.location());
2022         layer->setSize(scrollCornerAndResizer.size());
2023         layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
2024     }
2025 #endif
2026 
2027     if (m_scrollCorner)
2028         m_scrollCorner->setFrameRect(scrollCorner);
2029     if (m_resizer)
2030         m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
2031 }
2032 
scrollWidth()2033 int RenderLayer::scrollWidth()
2034 {
2035     if (m_scrollDimensionsDirty)
2036         computeScrollDimensions();
2037     return m_scrollWidth;
2038 }
2039 
scrollHeight()2040 int RenderLayer::scrollHeight()
2041 {
2042     if (m_scrollDimensionsDirty)
2043         computeScrollDimensions();
2044     return m_scrollHeight;
2045 }
2046 
overflowTop() const2047 int RenderLayer::overflowTop() const
2048 {
2049     RenderBox* box = renderBox();
2050     IntRect overflowRect(box->layoutOverflowRect());
2051     box->flipForWritingMode(overflowRect);
2052     return overflowRect.y();
2053 }
2054 
overflowBottom() const2055 int RenderLayer::overflowBottom() const
2056 {
2057     RenderBox* box = renderBox();
2058     IntRect overflowRect(box->layoutOverflowRect());
2059     box->flipForWritingMode(overflowRect);
2060     return overflowRect.maxY();
2061 }
2062 
overflowLeft() const2063 int RenderLayer::overflowLeft() const
2064 {
2065     RenderBox* box = renderBox();
2066     IntRect overflowRect(box->layoutOverflowRect());
2067     box->flipForWritingMode(overflowRect);
2068     return overflowRect.x();
2069 }
2070 
overflowRight() const2071 int RenderLayer::overflowRight() const
2072 {
2073     RenderBox* box = renderBox();
2074     IntRect overflowRect(box->layoutOverflowRect());
2075     box->flipForWritingMode(overflowRect);
2076     return overflowRect.maxX();
2077 }
2078 
computeScrollDimensions(bool * needHBar,bool * needVBar)2079 void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
2080 {
2081     RenderBox* box = renderBox();
2082     ASSERT(box);
2083 
2084     m_scrollDimensionsDirty = false;
2085 
2086     m_scrollLeftOverflow = overflowLeft() - box->borderLeft();
2087     m_scrollTopOverflow = overflowTop() - box->borderTop();
2088 
2089     m_scrollWidth = overflowRight() - overflowLeft();
2090     m_scrollHeight = overflowBottom() - overflowTop();
2091 
2092     m_scrollOrigin = IntPoint(-m_scrollLeftOverflow, -m_scrollTopOverflow);
2093 
2094     if (needHBar)
2095         *needHBar = m_scrollWidth > box->clientWidth();
2096     if (needVBar)
2097         *needVBar = m_scrollHeight > box->clientHeight();
2098 }
2099 
updateOverflowStatus(bool horizontalOverflow,bool verticalOverflow)2100 void RenderLayer::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
2101 {
2102     if (m_overflowStatusDirty) {
2103         m_horizontalOverflow = horizontalOverflow;
2104         m_verticalOverflow = verticalOverflow;
2105         m_overflowStatusDirty = false;
2106         return;
2107     }
2108 
2109     bool horizontalOverflowChanged = (m_horizontalOverflow != horizontalOverflow);
2110     bool verticalOverflowChanged = (m_verticalOverflow != verticalOverflow);
2111 
2112     if (horizontalOverflowChanged || verticalOverflowChanged) {
2113         m_horizontalOverflow = horizontalOverflow;
2114         m_verticalOverflow = verticalOverflow;
2115 
2116         if (FrameView* frameView = renderer()->document()->view()) {
2117             frameView->scheduleEvent(OverflowEvent::create(horizontalOverflowChanged, horizontalOverflow, verticalOverflowChanged, verticalOverflow),
2118                 renderer()->node());
2119         }
2120     }
2121 }
2122 
updateScrollInfoAfterLayout()2123 void RenderLayer::updateScrollInfoAfterLayout()
2124 {
2125     RenderBox* box = renderBox();
2126     if (!box)
2127         return;
2128 
2129     m_scrollDimensionsDirty = true;
2130 
2131     bool horizontalOverflow, verticalOverflow;
2132     computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
2133 
2134     if (box->style()->overflowX() != OMARQUEE) {
2135         // Layout may cause us to be in an invalid scroll position.  In this case we need
2136         // to pull our scroll offsets back to the max (or push them up to the min).
2137         int newX = max(0, min(scrollXOffset(), scrollWidth() - box->clientWidth()));
2138         int newY = max(0, min(scrollYOffset(), scrollHeight() - box->clientHeight()));
2139         if (newX != scrollXOffset() || newY != scrollYOffset()) {
2140             RenderView* view = renderer()->view();
2141             ASSERT(view);
2142             // scrollToOffset() may call updateLayerPositions(), which doesn't work
2143             // with LayoutState.
2144             // FIXME: Remove the disableLayoutState/enableLayoutState if the above changes.
2145             if (view)
2146                 view->disableLayoutState();
2147             scrollToOffset(newX, newY);
2148             if (view)
2149                 view->enableLayoutState();
2150         }
2151     }
2152 
2153     bool haveHorizontalBar = m_hBar;
2154     bool haveVerticalBar = m_vBar;
2155 
2156     // overflow:scroll should just enable/disable.
2157     if (renderer()->style()->overflowX() == OSCROLL)
2158         m_hBar->setEnabled(horizontalOverflow);
2159     if (renderer()->style()->overflowY() == OSCROLL)
2160         m_vBar->setEnabled(verticalOverflow);
2161 
2162     // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
2163     // scrollbars that may be present.
2164     if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar)
2165         setHasHorizontalScrollbar(false);
2166     if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar)
2167         setHasVerticalScrollbar(false);
2168 
2169     // overflow:auto may need to lay out again if scrollbars got added/removed.
2170     bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
2171                              (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
2172     if (scrollbarsChanged) {
2173         if (box->hasAutoHorizontalScrollbar())
2174             setHasHorizontalScrollbar(horizontalOverflow);
2175         if (box->hasAutoVerticalScrollbar())
2176             setHasVerticalScrollbar(verticalOverflow);
2177 
2178 #if ENABLE(DASHBOARD_SUPPORT)
2179         // Force an update since we know the scrollbars have changed things.
2180         if (renderer()->document()->hasDashboardRegions())
2181             renderer()->document()->setDashboardRegionsDirty(true);
2182 #endif
2183 
2184         renderer()->repaint();
2185 
2186         if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) {
2187             if (!m_inOverflowRelayout) {
2188                 // Our proprietary overflow: overlay value doesn't trigger a layout.
2189                 m_inOverflowRelayout = true;
2190                 renderer()->setNeedsLayout(true, false);
2191                 if (renderer()->isRenderBlock()) {
2192                     RenderBlock* block = toRenderBlock(renderer());
2193                     block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow,
2194                                              box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
2195                     block->layoutBlock(true);
2196                 } else
2197                     renderer()->layout();
2198                 m_inOverflowRelayout = false;
2199             }
2200         }
2201     }
2202 
2203     // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
2204     if (m_hBar && box->hasAutoHorizontalScrollbar())
2205         m_hBar->setEnabled(true);
2206     if (m_vBar && box->hasAutoVerticalScrollbar())
2207         m_vBar->setEnabled(true);
2208 
2209     // Set up the range (and page step/line step).
2210     if (m_hBar) {
2211         int clientWidth = box->clientWidth();
2212         int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
2213         m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
2214         m_hBar->setProportion(clientWidth, m_scrollWidth);
2215     }
2216     if (m_vBar) {
2217         int clientHeight = box->clientHeight();
2218         int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
2219         m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
2220         m_vBar->setProportion(clientHeight, m_scrollHeight);
2221     }
2222 
2223     RenderView* view = renderer()->view();
2224     view->disableLayoutState();
2225     scrollToOffset(scrollXOffset(), scrollYOffset());
2226     view->enableLayoutState();
2227 
2228     if (renderer()->node() && renderer()->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER))
2229         updateOverflowStatus(horizontalOverflow, verticalOverflow);
2230 }
2231 
paintOverflowControls(GraphicsContext * context,int tx,int ty,const IntRect & damageRect,bool paintingOverlayControls)2232 void RenderLayer::paintOverflowControls(GraphicsContext* context, int tx, int ty, const IntRect& damageRect, bool paintingOverlayControls)
2233 {
2234     // Don't do anything if we have no overflow.
2235     if (!renderer()->hasOverflowClip())
2236         return;
2237 
2238     // Overlay scrollbars paint in a second pass through the layer tree so that they will paint
2239     // on top of everything else. If this is the normal painting pass, paintingOverlayControls
2240     // will be false, and we should just tell the root layer that there are overlay scrollbars
2241     // that need to be painted. That will cause the second pass through the layer tree to run,
2242     // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the
2243     // second pass doesn't need to re-enter the RenderTree to get it right.
2244     if (hasOverlayScrollbars() && !paintingOverlayControls) {
2245         RenderView* renderView = renderer()->view();
2246         renderView->layer()->setContainsDirtyOverlayScrollbars(true);
2247         m_cachedOverlayScrollbarOffset = IntPoint(tx, ty);
2248         renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true);
2249         return;
2250     }
2251 
2252     int offsetX = tx;
2253     int offsetY = ty;
2254     if (paintingOverlayControls) {
2255         offsetX = m_cachedOverlayScrollbarOffset.x();
2256         offsetY = m_cachedOverlayScrollbarOffset.y();
2257     }
2258 
2259     // Move the scrollbar widgets if necessary.  We normally move and resize widgets during layout, but sometimes
2260     // widgets can move without layout occurring (most notably when you scroll a document that
2261     // contains fixed positioned elements).
2262     positionOverflowControls(offsetX, offsetY);
2263 
2264     // Now that we're sure the scrollbars are in the right place, paint them.
2265     if (m_hBar
2266 #if USE(ACCELERATED_COMPOSITING)
2267         && !layerForHorizontalScrollbar()
2268 #endif
2269               )
2270         m_hBar->paint(context, damageRect);
2271     if (m_vBar
2272 #if USE(ACCELERATED_COMPOSITING)
2273         && !layerForVerticalScrollbar()
2274 #endif
2275               )
2276         m_vBar->paint(context, damageRect);
2277 
2278 #if USE(ACCELERATED_COMPOSITING)
2279     if (layerForScrollCorner())
2280         return;
2281 #endif
2282 
2283     // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the
2284     // edge of the box.
2285     paintScrollCorner(context, offsetX, offsetY, damageRect);
2286 
2287     // Paint our resizer last, since it sits on top of the scroll corner.
2288     paintResizer(context, offsetX, offsetY, damageRect);
2289 }
2290 
paintScrollCorner(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)2291 void RenderLayer::paintScrollCorner(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
2292 {
2293     RenderBox* box = renderBox();
2294     ASSERT(box);
2295 
2296     IntRect cornerRect = scrollCornerRect();
2297     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
2298     if (!absRect.intersects(damageRect))
2299         return;
2300 
2301     if (context->updatingControlTints()) {
2302         updateScrollCornerStyle();
2303         return;
2304     }
2305 
2306     if (m_scrollCorner) {
2307         m_scrollCorner->paintIntoRect(context, tx, ty, absRect);
2308         return;
2309     }
2310 
2311     // We don't want to paint white if we have overlay scrollbars, since we need
2312     // to see what is behind it.
2313     if (!hasOverlayScrollbars())
2314         context->fillRect(absRect, Color::white, box->style()->colorSpace());
2315 }
2316 
paintResizer(GraphicsContext * context,int tx,int ty,const IntRect & damageRect)2317 void RenderLayer::paintResizer(GraphicsContext* context, int tx, int ty, const IntRect& damageRect)
2318 {
2319     if (renderer()->style()->resize() == RESIZE_NONE)
2320         return;
2321 
2322     RenderBox* box = renderBox();
2323     ASSERT(box);
2324 
2325     IntRect cornerRect = resizerCornerRect(this, box->borderBoxRect());
2326     IntRect absRect = IntRect(cornerRect.x() + tx, cornerRect.y() + ty, cornerRect.width(), cornerRect.height());
2327     if (!absRect.intersects(damageRect))
2328         return;
2329 
2330     if (context->updatingControlTints()) {
2331         updateResizerStyle();
2332         return;
2333     }
2334 
2335     if (m_resizer) {
2336         m_resizer->paintIntoRect(context, tx, ty, absRect);
2337         return;
2338     }
2339 
2340     // Paint the resizer control.
2341     DEFINE_STATIC_LOCAL(RefPtr<Image>, resizeCornerImage, (Image::loadPlatformResource("textAreaResizeCorner")));
2342     IntPoint imagePoint(absRect.maxX() - resizeCornerImage->width(), absRect.maxY() - resizeCornerImage->height());
2343     context->drawImage(resizeCornerImage.get(), box->style()->colorSpace(), imagePoint);
2344 
2345     // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
2346     // Clipping will exclude the right and bottom edges of this frame.
2347     if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) {
2348         GraphicsContextStateSaver stateSaver(*context);
2349         context->clip(absRect);
2350         IntRect largerCorner = absRect;
2351         largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
2352         context->setStrokeColor(Color(makeRGB(217, 217, 217)), ColorSpaceDeviceRGB);
2353         context->setStrokeThickness(1.0f);
2354         context->setFillColor(Color::transparent, ColorSpaceDeviceRGB);
2355         context->drawRect(largerCorner);
2356     }
2357 }
2358 
isPointInResizeControl(const IntPoint & absolutePoint) const2359 bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
2360 {
2361     if (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE)
2362         return false;
2363 
2364     RenderBox* box = renderBox();
2365     ASSERT(box);
2366 
2367     IntPoint localPoint = absoluteToContents(absolutePoint);
2368 
2369     IntRect localBounds(0, 0, box->width(), box->height());
2370     return resizerCornerRect(this, localBounds).contains(localPoint);
2371 }
2372 
hitTestOverflowControls(HitTestResult & result,const IntPoint & localPoint)2373 bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
2374 {
2375     if (!m_hBar && !m_vBar && (!renderer()->hasOverflowClip() || renderer()->style()->resize() == RESIZE_NONE))
2376         return false;
2377 
2378     RenderBox* box = renderBox();
2379     ASSERT(box);
2380 
2381     IntRect resizeControlRect;
2382     if (renderer()->style()->resize() != RESIZE_NONE) {
2383         resizeControlRect = resizerCornerRect(this, box->borderBoxRect());
2384         if (resizeControlRect.contains(localPoint))
2385             return true;
2386     }
2387 
2388     int resizeControlSize = max(resizeControlRect.height(), 0);
2389 
2390     if (m_vBar) {
2391         IntRect vBarRect(box->width() - box->borderRight() - m_vBar->width(),
2392                          box->borderTop(),
2393                          m_vBar->width(),
2394                          box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
2395         if (vBarRect.contains(localPoint)) {
2396             result.setScrollbar(m_vBar.get());
2397             return true;
2398         }
2399     }
2400 
2401     resizeControlSize = max(resizeControlRect.width(), 0);
2402     if (m_hBar) {
2403         IntRect hBarRect(box->borderLeft(),
2404                          box->height() - box->borderBottom() - m_hBar->height(),
2405                          box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
2406                          m_hBar->height());
2407         if (hBarRect.contains(localPoint)) {
2408             result.setScrollbar(m_hBar.get());
2409             return true;
2410         }
2411     }
2412 
2413     return false;
2414 }
2415 
scroll(ScrollDirection direction,ScrollGranularity granularity,float multiplier)2416 bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
2417 {
2418     return ScrollableArea::scroll(direction, granularity, multiplier);
2419 }
2420 
paint(GraphicsContext * p,const IntRect & damageRect,PaintBehavior paintBehavior,RenderObject * paintingRoot)2421 void RenderLayer::paint(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot)
2422 {
2423     OverlapTestRequestMap overlapTestRequests;
2424     paintLayer(this, p, damageRect, paintBehavior, paintingRoot, &overlapTestRequests);
2425     OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2426     for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
2427         it->first->setOverlapTestResult(false);
2428 }
2429 
paintOverlayScrollbars(GraphicsContext * p,const IntRect & damageRect,PaintBehavior paintBehavior,RenderObject * paintingRoot)2430 void RenderLayer::paintOverlayScrollbars(GraphicsContext* p, const IntRect& damageRect, PaintBehavior paintBehavior, RenderObject *paintingRoot)
2431 {
2432     if (!m_containsDirtyOverlayScrollbars)
2433         return;
2434     paintLayer(this, p, damageRect, paintBehavior, paintingRoot, 0, PaintLayerHaveTransparency | PaintLayerTemporaryClipRects
2435                | PaintLayerPaintingOverlayScrollbars);
2436     m_containsDirtyOverlayScrollbars = false;
2437 }
2438 
setClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)2439 static void setClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
2440 {
2441     if (paintDirtyRect == clipRect)
2442         return;
2443     p->save();
2444     p->clip(clipRect);
2445 }
2446 
restoreClip(GraphicsContext * p,const IntRect & paintDirtyRect,const IntRect & clipRect)2447 static void restoreClip(GraphicsContext* p, const IntRect& paintDirtyRect, const IntRect& clipRect)
2448 {
2449     if (paintDirtyRect == clipRect)
2450         return;
2451     p->restore();
2452 }
2453 
performOverlapTests(OverlapTestRequestMap & overlapTestRequests,const RenderLayer * rootLayer,const RenderLayer * layer)2454 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
2455 {
2456     Vector<OverlapTestRequestClient*> overlappedRequestClients;
2457     OverlapTestRequestMap::iterator end = overlapTestRequests.end();
2458     IntRect boundingBox = layer->boundingBox(rootLayer);
2459     for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
2460         if (!boundingBox.intersects(it->second))
2461             continue;
2462 
2463         it->first->setOverlapTestResult(true);
2464         overlappedRequestClients.append(it->first);
2465     }
2466     for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
2467         overlapTestRequests.remove(overlappedRequestClients[i]);
2468 }
2469 
2470 #if USE(ACCELERATED_COMPOSITING)
shouldDoSoftwarePaint(const RenderLayer * layer,bool paintingReflection)2471 static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
2472 {
2473     return paintingReflection && !layer->has3DTransform();
2474 }
2475 #endif
2476 
paintLayer(RenderLayer * rootLayer,GraphicsContext * p,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags)2477 void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
2478                         const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2479                         RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2480                         PaintLayerFlags paintFlags)
2481 {
2482 #if USE(ACCELERATED_COMPOSITING)
2483     if (isComposited()) {
2484         // The updatingControlTints() painting pass goes through compositing layers,
2485         // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
2486         if (p->updatingControlTints() || (paintBehavior & PaintBehaviorFlattenCompositingLayers))
2487             paintFlags |= PaintLayerTemporaryClipRects;
2488         else if (!backing()->paintingGoesToWindow() && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
2489             // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
2490             return;
2491         }
2492     }
2493 #endif
2494 
2495     // Avoid painting layers when stylesheets haven't loaded.  This eliminates FOUC.
2496     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
2497     // will do a full repaint().
2498     if (renderer()->document()->didLayoutWithPendingStylesheets() && !renderer()->isRenderView() && !renderer()->isRoot())
2499         return;
2500 
2501     // If this layer is totally invisible then there is nothing to paint.
2502     if (!renderer()->opacity())
2503         return;
2504 
2505     if (paintsWithTransparency(paintBehavior))
2506         paintFlags |= PaintLayerHaveTransparency;
2507 
2508     // Apply a transform if we have one.  A reflection is considered to be a transform, since it is a flip and a translate.
2509     if (paintsWithTransform(paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
2510         TransformationMatrix layerTransform = renderableTransform(paintBehavior);
2511         // If the transform can't be inverted, then don't paint anything.
2512         if (!layerTransform.isInvertible())
2513             return;
2514 
2515         // If we have a transparency layer enclosing us and we are the root of a transform, then we need to establish the transparency
2516         // layer from the parent now, assuming there is a parent
2517         if (paintFlags & PaintLayerHaveTransparency) {
2518             if (parent())
2519                 parent()->beginTransparencyLayers(p, rootLayer, paintBehavior);
2520             else
2521                 beginTransparencyLayers(p, rootLayer, paintBehavior);
2522         }
2523 
2524         // Make sure the parent's clip rects have been calculated.
2525         IntRect clipRect = paintDirtyRect;
2526         if (parent()) {
2527             clipRect = backgroundClipRect(rootLayer, paintFlags & PaintLayerTemporaryClipRects);
2528             clipRect.intersect(paintDirtyRect);
2529         }
2530 
2531         // Push the parent coordinate space's clip.
2532         setClip(p, paintDirtyRect, clipRect);
2533 
2534         // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
2535         // This involves subtracting out the position of the layer in our current coordinate space.
2536         int x = 0;
2537         int y = 0;
2538         convertToLayerCoords(rootLayer, x, y);
2539         TransformationMatrix transform(layerTransform);
2540         transform.translateRight(x, y);
2541 
2542         // Apply the transform.
2543         {
2544             GraphicsContextStateSaver stateSaver(*p);
2545             p->concatCTM(transform.toAffineTransform());
2546 
2547             // Now do a paint with the root layer shifted to be us.
2548             paintLayer(this, p, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, overlapTestRequests, paintFlags | PaintLayerAppliedTransform);
2549         }
2550 
2551         // Restore the clip.
2552         restoreClip(p, paintDirtyRect, clipRect);
2553 
2554         return;
2555     }
2556 
2557     PaintLayerFlags localPaintFlags = paintFlags & ~PaintLayerAppliedTransform;
2558     bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency;
2559 
2560     // Paint the reflection first if we have one.
2561     if (m_reflection && !m_paintingInsideReflection) {
2562         // Mark that we are now inside replica painting.
2563         m_paintingInsideReflection = true;
2564         reflectionLayer()->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags | PaintLayerPaintingReflection);
2565         m_paintingInsideReflection = false;
2566     }
2567 
2568     // Calculate the clip rects we should use.
2569     IntRect layerBounds, damageRect, clipRectToApply, outlineRect;
2570     calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect, localPaintFlags & PaintLayerTemporaryClipRects);
2571     int x = layerBounds.x();
2572     int y = layerBounds.y();
2573     int tx = x - renderBoxX();
2574     int ty = y - renderBoxY();
2575 
2576     // Ensure our lists are up-to-date.
2577     updateCompositingAndLayerListsIfNeeded();
2578 
2579     bool forceBlackText = paintBehavior & PaintBehaviorForceBlackText;
2580     bool selectionOnly  = paintBehavior & PaintBehaviorSelectionOnly;
2581 
2582     // If this layer's renderer is a child of the paintingRoot, we render unconditionally, which
2583     // is done by passing a nil paintingRoot down to our renderer (as if no paintingRoot was ever set).
2584     // Else, our renderer tree may or may not contain the painting root, so we pass that root along
2585     // so it will be tested against as we descend through the renderers.
2586     RenderObject* paintingRootForRenderer = 0;
2587     if (paintingRoot && !renderer()->isDescendantOf(paintingRoot))
2588         paintingRootForRenderer = paintingRoot;
2589 
2590     if (overlapTestRequests && isSelfPaintingLayer())
2591         performOverlapTests(*overlapTestRequests, rootLayer, this);
2592 
2593     bool paintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars;
2594 
2595     // We want to paint our layer, but only if we intersect the damage rect.
2596     bool shouldPaint = intersectsDamageRect(layerBounds, damageRect, rootLayer) && m_hasVisibleContent && isSelfPaintingLayer();
2597     if (shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) {
2598         // Begin transparency layers lazily now that we know we have to paint something.
2599         if (haveTransparency)
2600             beginTransparencyLayers(p, rootLayer, paintBehavior);
2601 
2602         // Paint our background first, before painting any child layers.
2603         // Establish the clip used to paint our background.
2604         setClip(p, paintDirtyRect, damageRect);
2605 
2606         // Paint the background.
2607         PaintInfo paintInfo(p, damageRect, PaintPhaseBlockBackground, false, paintingRootForRenderer, 0);
2608         renderer()->paint(paintInfo, tx, ty);
2609 
2610         // Restore the clip.
2611         restoreClip(p, paintDirtyRect, damageRect);
2612     }
2613 
2614     // Now walk the sorted list of children with negative z-indices.
2615     paintList(m_negZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2616 
2617     // Now establish the appropriate clip and paint our child RenderObjects.
2618     if (shouldPaint && !clipRectToApply.isEmpty() && !paintingOverlayScrollbars) {
2619         // Begin transparency layers lazily now that we know we have to paint something.
2620         if (haveTransparency)
2621             beginTransparencyLayers(p, rootLayer, paintBehavior);
2622 
2623         // Set up the clip used when painting our children.
2624         setClip(p, paintDirtyRect, clipRectToApply);
2625         PaintInfo paintInfo(p, clipRectToApply,
2626                                           selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds,
2627                                           forceBlackText, paintingRootForRenderer, 0);
2628         renderer()->paint(paintInfo, tx, ty);
2629         if (!selectionOnly) {
2630             paintInfo.phase = PaintPhaseFloat;
2631             renderer()->paint(paintInfo, tx, ty);
2632             paintInfo.phase = PaintPhaseForeground;
2633             paintInfo.overlapTestRequests = overlapTestRequests;
2634             renderer()->paint(paintInfo, tx, ty);
2635             paintInfo.phase = PaintPhaseChildOutlines;
2636             renderer()->paint(paintInfo, tx, ty);
2637         }
2638 
2639         // Now restore our clip.
2640         restoreClip(p, paintDirtyRect, clipRectToApply);
2641     }
2642 
2643     if (!outlineRect.isEmpty() && isSelfPaintingLayer() && !paintingOverlayScrollbars) {
2644         // Paint our own outline
2645         PaintInfo paintInfo(p, outlineRect, PaintPhaseSelfOutline, false, paintingRootForRenderer, 0);
2646         setClip(p, paintDirtyRect, outlineRect);
2647         renderer()->paint(paintInfo, tx, ty);
2648         restoreClip(p, paintDirtyRect, outlineRect);
2649     }
2650 
2651     // Paint any child layers that have overflow.
2652     paintList(m_normalFlowList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2653 
2654     // Now walk the sorted list of children with positive z-indices.
2655     paintList(m_posZOrderList, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, localPaintFlags);
2656 
2657     if (renderer()->hasMask() && shouldPaint && !selectionOnly && !damageRect.isEmpty() && !paintingOverlayScrollbars) {
2658         setClip(p, paintDirtyRect, damageRect);
2659 
2660         // Paint the mask.
2661         PaintInfo paintInfo(p, damageRect, PaintPhaseMask, false, paintingRootForRenderer, 0);
2662         renderer()->paint(paintInfo, tx, ty);
2663 
2664         // Restore the clip.
2665         restoreClip(p, paintDirtyRect, damageRect);
2666     }
2667 
2668     if (paintingOverlayScrollbars) {
2669         setClip(p, paintDirtyRect, damageRect);
2670         paintOverflowControls(p, tx, ty, damageRect, true);
2671         restoreClip(p, paintDirtyRect, damageRect);
2672     }
2673 
2674     // End our transparency layer
2675     if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
2676         p->endTransparencyLayer();
2677         p->restore();
2678         m_usedTransparency = false;
2679     }
2680 }
2681 
paintList(Vector<RenderLayer * > * list,RenderLayer * rootLayer,GraphicsContext * p,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags)2682 void RenderLayer::paintList(Vector<RenderLayer*>* list, RenderLayer* rootLayer, GraphicsContext* p,
2683                             const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2684                             RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2685                             PaintLayerFlags paintFlags)
2686 {
2687     if (!list)
2688         return;
2689 
2690     for (size_t i = 0; i < list->size(); ++i) {
2691         RenderLayer* childLayer = list->at(i);
2692         if (!childLayer->isPaginated())
2693             childLayer->paintLayer(rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
2694         else
2695             paintPaginatedChildLayer(childLayer, rootLayer, p, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
2696     }
2697 }
2698 
paintPaginatedChildLayer(RenderLayer * childLayer,RenderLayer * rootLayer,GraphicsContext * context,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags)2699 void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
2700                                            const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2701                                            RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2702                                            PaintLayerFlags paintFlags)
2703 {
2704     // We need to do multiple passes, breaking up our child layer into strips.
2705     Vector<RenderLayer*> columnLayers;
2706     RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
2707     for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
2708         if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
2709             columnLayers.append(curr);
2710         if (curr == ancestorLayer)
2711             break;
2712     }
2713 
2714     ASSERT(columnLayers.size());
2715 
2716     paintChildLayerIntoColumns(childLayer, rootLayer, context, paintDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags, columnLayers, columnLayers.size() - 1);
2717 }
2718 
paintChildLayerIntoColumns(RenderLayer * childLayer,RenderLayer * rootLayer,GraphicsContext * context,const IntRect & paintDirtyRect,PaintBehavior paintBehavior,RenderObject * paintingRoot,OverlapTestRequestMap * overlapTestRequests,PaintLayerFlags paintFlags,const Vector<RenderLayer * > & columnLayers,size_t colIndex)2719 void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, RenderLayer* rootLayer, GraphicsContext* context,
2720                                              const IntRect& paintDirtyRect, PaintBehavior paintBehavior,
2721                                              RenderObject* paintingRoot, OverlapTestRequestMap* overlapTestRequests,
2722                                              PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
2723 {
2724     RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
2725 
2726     ASSERT(columnBlock && columnBlock->hasColumns());
2727     if (!columnBlock || !columnBlock->hasColumns())
2728         return;
2729 
2730     int layerX = 0;
2731     int layerY = 0;
2732     columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
2733 
2734     bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
2735 
2736     ColumnInfo* colInfo = columnBlock->columnInfo();
2737     unsigned colCount = columnBlock->columnCount(colInfo);
2738     int currLogicalTopOffset = 0;
2739     for (unsigned i = 0; i < colCount; i++) {
2740         // For each rect, we clip to the rect, and then we adjust our coords.
2741         IntRect colRect = columnBlock->columnRectAt(colInfo, i);
2742         columnBlock->flipForWritingMode(colRect);
2743         int logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent();
2744         IntSize offset = isHorizontal ? IntSize(logicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, logicalLeftOffset);
2745 
2746         colRect.move(layerX, layerY);
2747 
2748         IntRect localDirtyRect(paintDirtyRect);
2749         localDirtyRect.intersect(colRect);
2750 
2751         if (!localDirtyRect.isEmpty()) {
2752             GraphicsContextStateSaver stateSaver(*context);
2753 
2754             // Each strip pushes a clip, since column boxes are specified as being
2755             // like overflow:hidden.
2756             context->clip(colRect);
2757 
2758             if (!colIndex) {
2759                 // Apply a translation transform to change where the layer paints.
2760                 TransformationMatrix oldTransform;
2761                 bool oldHasTransform = childLayer->transform();
2762                 if (oldHasTransform)
2763                     oldTransform = *childLayer->transform();
2764                 TransformationMatrix newTransform(oldTransform);
2765                 newTransform.translateRight(offset.width(), offset.height());
2766 
2767                 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
2768                 childLayer->paintLayer(rootLayer, context, localDirtyRect, paintBehavior, paintingRoot, overlapTestRequests, paintFlags);
2769                 if (oldHasTransform)
2770                     childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
2771                 else
2772                     childLayer->m_transform.clear();
2773             } else {
2774                 // Adjust the transform such that the renderer's upper left corner will paint at (0,0) in user space.
2775                 // This involves subtracting out the position of the layer in our current coordinate space.
2776                 int childX = 0;
2777                 int childY = 0;
2778                 columnLayers[colIndex - 1]->convertToLayerCoords(rootLayer, childX, childY);
2779                 TransformationMatrix transform;
2780                 transform.translateRight(childX + offset.width(), childY + offset.height());
2781 
2782                 // Apply the transform.
2783                 context->concatCTM(transform.toAffineTransform());
2784 
2785                 // Now do a paint with the root layer shifted to be the next multicol block.
2786                 paintChildLayerIntoColumns(childLayer, columnLayers[colIndex - 1], context, transform.inverse().mapRect(localDirtyRect), paintBehavior,
2787                                            paintingRoot, overlapTestRequests, paintFlags,
2788                                            columnLayers, colIndex - 1);
2789             }
2790         }
2791 
2792         // Move to the next position.
2793         int blockDelta = isHorizontal ? colRect.height() : colRect.width();
2794         if (columnBlock->style()->isFlippedBlocksWritingMode())
2795             currLogicalTopOffset += blockDelta;
2796         else
2797             currLogicalTopOffset -= blockDelta;
2798     }
2799 }
2800 
frameVisibleRect(RenderObject * renderer)2801 static inline IntRect frameVisibleRect(RenderObject* renderer)
2802 {
2803     FrameView* frameView = renderer->document()->view();
2804     if (!frameView)
2805         return IntRect();
2806 
2807     return frameView->visibleContentRect();
2808 }
2809 
hitTest(const HitTestRequest & request,HitTestResult & result)2810 bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
2811 {
2812     renderer()->document()->updateLayout();
2813 
2814     IntRect hitTestArea = renderer()->view()->documentRect();
2815     if (!request.ignoreClipping())
2816         hitTestArea.intersect(frameVisibleRect(renderer()));
2817 
2818     RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, result.point(), false);
2819     if (!insideLayer) {
2820         // We didn't hit any layer. If we are the root layer and the mouse is -- or just was -- down,
2821         // return ourselves. We do this so mouse events continue getting delivered after a drag has
2822         // exited the WebView, and so hit testing over a scrollbar hits the content document.
2823         if ((request.active() || request.mouseUp()) && renderer()->isRenderView()) {
2824             renderer()->updateHitTestResult(result, result.point());
2825             insideLayer = this;
2826         }
2827     }
2828 
2829     // Now determine if the result is inside an anchor - if the urlElement isn't already set.
2830     Node* node = result.innerNode();
2831     if (node && !result.URLElement())
2832         result.setURLElement(static_cast<Element*>(node->enclosingLinkEventParentOrSelf()));
2833 
2834     // Next set up the correct :hover/:active state along the new chain.
2835     updateHoverActiveState(request, result);
2836 
2837     // Now return whether we were inside this layer (this will always be true for the root
2838     // layer).
2839     return insideLayer;
2840 }
2841 
enclosingElement() const2842 Node* RenderLayer::enclosingElement() const
2843 {
2844     for (RenderObject* r = renderer(); r; r = r->parent()) {
2845         if (Node* e = r->node())
2846             return e;
2847     }
2848     ASSERT_NOT_REACHED();
2849     return 0;
2850 }
2851 
2852 // Compute the z-offset of the point in the transformState.
2853 // This is effectively projecting a ray normal to the plane of ancestor, finding where that
2854 // ray intersects target, and computing the z delta between those two points.
computeZOffset(const HitTestingTransformState & transformState)2855 static double computeZOffset(const HitTestingTransformState& transformState)
2856 {
2857     // We got an affine transform, so no z-offset
2858     if (transformState.m_accumulatedTransform.isAffine())
2859         return 0;
2860 
2861     // Flatten the point into the target plane
2862     FloatPoint targetPoint = transformState.mappedPoint();
2863 
2864     // Now map the point back through the transform, which computes Z.
2865     FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
2866     return backmappedPoint.z();
2867 }
2868 
createLocalTransformState(RenderLayer * rootLayer,RenderLayer * containerLayer,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * containerTransformState) const2869 PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
2870                                         const IntRect& hitTestRect, const IntPoint& hitTestPoint,
2871                                         const HitTestingTransformState* containerTransformState) const
2872 {
2873     RefPtr<HitTestingTransformState> transformState;
2874     int offsetX = 0;
2875     int offsetY = 0;
2876     if (containerTransformState) {
2877         // If we're already computing transform state, then it's relative to the container (which we know is non-null).
2878         transformState = HitTestingTransformState::create(*containerTransformState);
2879         convertToLayerCoords(containerLayer, offsetX, offsetY);
2880     } else {
2881         // If this is the first time we need to make transform state, then base it off of hitTestPoint,
2882         // which is relative to rootLayer.
2883         transformState = HitTestingTransformState::create(hitTestPoint, FloatQuad(hitTestRect));
2884         convertToLayerCoords(rootLayer, offsetX, offsetY);
2885     }
2886 
2887     RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
2888     if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
2889         TransformationMatrix containerTransform;
2890         renderer()->getTransformFromContainer(containerRenderer, IntSize(offsetX, offsetY), containerTransform);
2891         transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
2892     } else {
2893         transformState->translate(offsetX, offsetY, HitTestingTransformState::AccumulateTransform);
2894     }
2895 
2896     return transformState;
2897 }
2898 
2899 
isHitCandidate(const RenderLayer * hitLayer,bool canDepthSort,double * zOffset,const HitTestingTransformState * transformState)2900 static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
2901 {
2902     if (!hitLayer)
2903         return false;
2904 
2905     // The hit layer is depth-sorting with other layers, so just say that it was hit.
2906     if (canDepthSort)
2907         return true;
2908 
2909     // We need to look at z-depth to decide if this layer was hit.
2910     if (zOffset) {
2911         ASSERT(transformState);
2912         // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
2913         double childZOffset = computeZOffset(*transformState);
2914         if (childZOffset > *zOffset) {
2915             *zOffset = childZOffset;
2916             return true;
2917         }
2918         return false;
2919     }
2920 
2921     return true;
2922 }
2923 
2924 // hitTestPoint and hitTestRect are relative to rootLayer.
2925 // A 'flattening' layer is one preserves3D() == false.
2926 // transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
2927 // transformState.m_lastPlanarPoint is the hitTestPoint in the plane of the containing flattening layer.
2928 // transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
2929 //
2930 // If zOffset is non-null (which indicates that the caller wants z offset information),
2931 //  *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)2932 RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
2933                                        const IntRect& hitTestRect, const IntPoint& hitTestPoint, bool appliedTransform,
2934                                        const HitTestingTransformState* transformState, double* zOffset)
2935 {
2936     // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
2937 
2938     bool useTemporaryClipRects = false;
2939 #if USE(ACCELERATED_COMPOSITING)
2940     useTemporaryClipRects = compositor()->inCompositingMode();
2941 #endif
2942     useTemporaryClipRects |= renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
2943 
2944     IntRect hitTestArea = result.rectForPoint(hitTestPoint);
2945 
2946     // Apply a transform if we have one.
2947     if (transform() && !appliedTransform) {
2948         // Make sure the parent's clip rects have been calculated.
2949         if (parent()) {
2950             IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects, IncludeOverlayScrollbarSize);
2951             // Go ahead and test the enclosing clip now.
2952             if (!clipRect.intersects(hitTestArea))
2953                 return 0;
2954         }
2955 
2956         // Create a transform state to accumulate this transform.
2957         RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
2958 
2959         // If the transform can't be inverted, then don't hit test this layer at all.
2960         if (!newTransformState->m_accumulatedTransform.isInvertible())
2961             return 0;
2962 
2963         // Compute the point and the hit test rect in the coords of this layer by using the values
2964         // from the transformState, which store the point and quad in the coords of the last flattened
2965         // layer, and the accumulated transform which lets up map through preserve-3d layers.
2966         //
2967         // We can't just map hitTestPoint and hitTestRect because they may have been flattened (losing z)
2968         // by our container.
2969         IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
2970         IntRect localHitTestRect;
2971 #if USE(ACCELERATED_COMPOSITING)
2972         if (isComposited()) {
2973             // It doesn't make sense to project hitTestRect into the plane of this layer, so use the same bounds we use for painting.
2974             localHitTestRect = backing()->compositedBounds();
2975         } else
2976 #endif
2977             localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
2978 
2979         // Now do a hit test with the root layer shifted to be us.
2980         return hitTestLayer(this, containerLayer, request, result, localHitTestRect, localPoint, true, newTransformState.get(), zOffset);
2981     }
2982 
2983     // Ensure our lists and 3d status are up-to-date.
2984     updateCompositingAndLayerListsIfNeeded();
2985     update3DTransformedDescendantStatus();
2986 
2987     RefPtr<HitTestingTransformState> localTransformState;
2988     if (appliedTransform) {
2989         // We computed the correct state in the caller (above code), so just reference it.
2990         ASSERT(transformState);
2991         localTransformState = const_cast<HitTestingTransformState*>(transformState);
2992     } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
2993         // We need transform state for the first time, or to offset the container state, so create it here.
2994         localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestPoint, transformState);
2995     }
2996 
2997     // Check for hit test on backface if backface-visibility is 'hidden'
2998     if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
2999         TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
3000         // If the z-vector of the matrix is negative, the back is facing towards the viewer.
3001         if (invertedMatrix.m33() < 0)
3002             return 0;
3003     }
3004 
3005     RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
3006     if (localTransformState && !preserves3D()) {
3007         // Keep a copy of the pre-flattening state, for computing z-offsets for the container
3008         unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
3009         // This layer is flattening, so flatten the state passed to descendants.
3010         localTransformState->flatten();
3011     }
3012 
3013     // Calculate the clip rects we should use.
3014     IntRect layerBounds;
3015     IntRect bgRect;
3016     IntRect fgRect;
3017     IntRect outlineRect;
3018     calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects, IncludeOverlayScrollbarSize);
3019 
3020     // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
3021     // descendants.
3022     double localZOffset = -numeric_limits<double>::infinity();
3023     double* zOffsetForDescendantsPtr = 0;
3024     double* zOffsetForContentsPtr = 0;
3025 
3026     bool depthSortDescendants = false;
3027     if (preserves3D()) {
3028         depthSortDescendants = true;
3029         // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
3030         zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
3031         zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
3032     } else if (m_has3DTransformedDescendant) {
3033         // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
3034         depthSortDescendants = true;
3035         zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
3036         zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
3037     } else if (zOffset) {
3038         zOffsetForDescendantsPtr = 0;
3039         // Container needs us to give back a z offset for the hit layer.
3040         zOffsetForContentsPtr = zOffset;
3041     }
3042 
3043     // This variable tracks which layer the mouse ends up being inside.
3044     RenderLayer* candidateLayer = 0;
3045 
3046     // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
3047     RenderLayer* hitLayer = hitTestList(m_posZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
3048                                         localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3049     if (hitLayer) {
3050         if (!depthSortDescendants)
3051             return hitLayer;
3052         candidateLayer = hitLayer;
3053     }
3054 
3055     // Now check our overflow objects.
3056     hitLayer = hitTestList(m_normalFlowList, rootLayer, request, result, hitTestRect, hitTestPoint,
3057                            localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3058     if (hitLayer) {
3059         if (!depthSortDescendants)
3060             return hitLayer;
3061         candidateLayer = hitLayer;
3062     }
3063 
3064     // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
3065     if (fgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
3066         // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
3067         HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
3068         if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestDescendants) &&
3069             isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
3070             if (result.isRectBasedTest())
3071                 result.append(tempResult);
3072             else
3073                 result = tempResult;
3074             if (!depthSortDescendants)
3075                 return this;
3076             // Foreground can depth-sort with descendant layers, so keep this as a candidate.
3077             candidateLayer = this;
3078         } else if (result.isRectBasedTest())
3079             result.append(tempResult);
3080     }
3081 
3082     // Now check our negative z-index children.
3083     hitLayer = hitTestList(m_negZOrderList, rootLayer, request, result, hitTestRect, hitTestPoint,
3084                                         localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
3085     if (hitLayer) {
3086         if (!depthSortDescendants)
3087             return hitLayer;
3088         candidateLayer = hitLayer;
3089     }
3090 
3091     // If we found a layer, return. Child layers, and foreground always render in front of background.
3092     if (candidateLayer)
3093         return candidateLayer;
3094 
3095     if (bgRect.intersects(hitTestArea) && isSelfPaintingLayer()) {
3096         HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
3097         if (hitTestContents(request, tempResult, layerBounds, hitTestPoint, HitTestSelf) &&
3098             isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
3099             if (result.isRectBasedTest())
3100                 result.append(tempResult);
3101             else
3102                 result = tempResult;
3103             return this;
3104         } else if (result.isRectBasedTest())
3105             result.append(tempResult);
3106     }
3107 
3108     return 0;
3109 }
3110 
hitTestContents(const HitTestRequest & request,HitTestResult & result,const IntRect & layerBounds,const IntPoint & hitTestPoint,HitTestFilter hitTestFilter) const3111 bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const IntRect& layerBounds, const IntPoint& hitTestPoint, HitTestFilter hitTestFilter) const
3112 {
3113     if (!renderer()->hitTest(request, result, hitTestPoint,
3114                             layerBounds.x() - renderBoxX(),
3115                             layerBounds.y() - renderBoxY(),
3116                             hitTestFilter)) {
3117         // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
3118         // a rect-based test.
3119         ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size()));
3120         return false;
3121     }
3122 
3123     // For positioned generated content, we might still not have a
3124     // node by the time we get to the layer level, since none of
3125     // the content in the layer has an element. So just walk up
3126     // the tree.
3127     if (!result.innerNode() || !result.innerNonSharedNode()) {
3128         Node* e = enclosingElement();
3129         if (!result.innerNode())
3130             result.setInnerNode(e);
3131         if (!result.innerNonSharedNode())
3132             result.setInnerNonSharedNode(e);
3133     }
3134 
3135     return true;
3136 }
3137 
hitTestList(Vector<RenderLayer * > * list,RenderLayer * rootLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * transformState,double * zOffsetForDescendants,double * zOffset,const HitTestingTransformState * unflattenedTransformState,bool depthSortDescendants)3138 RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
3139                                       const HitTestRequest& request, HitTestResult& result,
3140                                       const IntRect& hitTestRect, const IntPoint& hitTestPoint,
3141                                       const HitTestingTransformState* transformState,
3142                                       double* zOffsetForDescendants, double* zOffset,
3143                                       const HitTestingTransformState* unflattenedTransformState,
3144                                       bool depthSortDescendants)
3145 {
3146     if (!list)
3147         return 0;
3148 
3149     RenderLayer* resultLayer = 0;
3150     for (int i = list->size() - 1; i >= 0; --i) {
3151         RenderLayer* childLayer = list->at(i);
3152         RenderLayer* hitLayer = 0;
3153         HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
3154         if (childLayer->isPaginated())
3155             hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestPoint, transformState, zOffsetForDescendants);
3156         else
3157             hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestPoint, false, transformState, zOffsetForDescendants);
3158 
3159         // If it a rect-based test, we can safely append the temporary result since it might had hit
3160         // nodes but not necesserily had hitLayer set.
3161         if (result.isRectBasedTest())
3162             result.append(tempResult);
3163 
3164         if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
3165             resultLayer = hitLayer;
3166             if (!result.isRectBasedTest())
3167                 result = tempResult;
3168             if (!depthSortDescendants)
3169                 break;
3170         }
3171     }
3172 
3173     return resultLayer;
3174 }
3175 
hitTestPaginatedChildLayer(RenderLayer * childLayer,RenderLayer * rootLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * transformState,double * zOffset)3176 RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3177                                                      const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset)
3178 {
3179     Vector<RenderLayer*> columnLayers;
3180     RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : stackingContext();
3181     for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
3182         if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
3183             columnLayers.append(curr);
3184         if (curr == ancestorLayer)
3185             break;
3186     }
3187 
3188     ASSERT(columnLayers.size());
3189     return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestPoint, transformState, zOffset,
3190                                     columnLayers, columnLayers.size() - 1);
3191 }
3192 
hitTestChildLayerColumns(RenderLayer * childLayer,RenderLayer * rootLayer,const HitTestRequest & request,HitTestResult & result,const IntRect & hitTestRect,const IntPoint & hitTestPoint,const HitTestingTransformState * transformState,double * zOffset,const Vector<RenderLayer * > & columnLayers,size_t columnIndex)3193 RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
3194                                                    const IntRect& hitTestRect, const IntPoint& hitTestPoint, const HitTestingTransformState* transformState, double* zOffset,
3195                                                    const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
3196 {
3197     RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
3198 
3199     ASSERT(columnBlock && columnBlock->hasColumns());
3200     if (!columnBlock || !columnBlock->hasColumns())
3201         return 0;
3202 
3203     int layerX = 0;
3204     int layerY = 0;
3205     columnBlock->layer()->convertToLayerCoords(rootLayer, layerX, layerY);
3206 
3207     ColumnInfo* colInfo = columnBlock->columnInfo();
3208     int colCount = columnBlock->columnCount(colInfo);
3209 
3210     // We have to go backwards from the last column to the first.
3211     bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
3212     int logicalLeft = columnBlock->logicalLeftOffsetForContent();
3213     int currLogicalTopOffset = 0;
3214     int i;
3215     for (i = 0; i < colCount; i++) {
3216         IntRect colRect = columnBlock->columnRectAt(colInfo, i);
3217         int blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
3218         if (columnBlock->style()->isFlippedBlocksWritingMode())
3219             currLogicalTopOffset += blockDelta;
3220         else
3221             currLogicalTopOffset -= blockDelta;
3222     }
3223     for (i = colCount - 1; i >= 0; i--) {
3224         // For each rect, we clip to the rect, and then we adjust our coords.
3225         IntRect colRect = columnBlock->columnRectAt(colInfo, i);
3226         columnBlock->flipForWritingMode(colRect);
3227         int currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft;
3228         int blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
3229         if (columnBlock->style()->isFlippedBlocksWritingMode())
3230             currLogicalTopOffset -= blockDelta;
3231         else
3232             currLogicalTopOffset += blockDelta;
3233         colRect.move(layerX, layerY);
3234 
3235         IntRect localClipRect(hitTestRect);
3236         localClipRect.intersect(colRect);
3237 
3238         IntSize offset = isHorizontal ? IntSize(currLogicalLeftOffset, currLogicalTopOffset) : IntSize(currLogicalTopOffset, currLogicalLeftOffset);
3239 
3240         if (!localClipRect.isEmpty() && localClipRect.intersects(result.rectForPoint(hitTestPoint))) {
3241             RenderLayer* hitLayer = 0;
3242             if (!columnIndex) {
3243                 // Apply a translation transform to change where the layer paints.
3244                 TransformationMatrix oldTransform;
3245                 bool oldHasTransform = childLayer->transform();
3246                 if (oldHasTransform)
3247                     oldTransform = *childLayer->transform();
3248                 TransformationMatrix newTransform(oldTransform);
3249                 newTransform.translateRight(offset.width(), offset.height());
3250 
3251                 childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
3252                 hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestPoint, false, transformState, zOffset);
3253                 if (oldHasTransform)
3254                     childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
3255                 else
3256                     childLayer->m_transform.clear();
3257             } else {
3258                 // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
3259                 // This involves subtracting out the position of the layer in our current coordinate space.
3260                 RenderLayer* nextLayer = columnLayers[columnIndex - 1];
3261                 RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestPoint, transformState);
3262                 newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform);
3263                 IntPoint localPoint = roundedIntPoint(newTransformState->mappedPoint());
3264                 IntRect localHitTestRect = newTransformState->mappedQuad().enclosingBoundingBox();
3265                 newTransformState->flatten();
3266 
3267                 hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, localPoint,
3268                                                     newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
3269             }
3270 
3271             if (hitLayer)
3272                 return hitLayer;
3273         }
3274     }
3275 
3276     return 0;
3277 }
3278 
updateClipRects(const RenderLayer * rootLayer,OverlayScrollbarSizeRelevancy relevancy)3279 void RenderLayer::updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy relevancy)
3280 {
3281     if (m_clipRects) {
3282         ASSERT(rootLayer == m_clipRectsRoot);
3283         return; // We have the correct cached value.
3284     }
3285 
3286     // For transformed layers, the root layer was shifted to be us, so there is no need to
3287     // examine the parent.  We want to cache clip rects with us as the root.
3288     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
3289     if (parentLayer)
3290         parentLayer->updateClipRects(rootLayer, relevancy);
3291 
3292     ClipRects clipRects;
3293     calculateClipRects(rootLayer, clipRects, true, relevancy);
3294 
3295     if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
3296         m_clipRects = parentLayer->clipRects();
3297     else
3298         m_clipRects = new (renderer()->renderArena()) ClipRects(clipRects);
3299     m_clipRects->ref();
3300 #ifndef NDEBUG
3301     m_clipRectsRoot = rootLayer;
3302 #endif
3303 }
3304 
calculateClipRects(const RenderLayer * rootLayer,ClipRects & clipRects,bool useCached,OverlayScrollbarSizeRelevancy relevancy) const3305 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached, OverlayScrollbarSizeRelevancy relevancy) const
3306 {
3307     if (!parent()) {
3308         // The root layer's clip rect is always infinite.
3309         clipRects.reset(PaintInfo::infiniteRect());
3310         return;
3311     }
3312 
3313     // For transformed layers, the root layer was shifted to be us, so there is no need to
3314     // examine the parent.  We want to cache clip rects with us as the root.
3315     RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
3316 
3317     // Ensure that our parent's clip has been calculated so that we can examine the values.
3318     if (parentLayer) {
3319         if (useCached && parentLayer->clipRects())
3320             clipRects = *parentLayer->clipRects();
3321         else
3322             parentLayer->calculateClipRects(rootLayer, clipRects);
3323     }
3324     else
3325         clipRects.reset(PaintInfo::infiniteRect());
3326 
3327     // A fixed object is essentially the root of its containing block hierarchy, so when
3328     // we encounter such an object, we reset our clip rects to the fixedClipRect.
3329     if (renderer()->style()->position() == FixedPosition) {
3330         clipRects.setPosClipRect(clipRects.fixedClipRect());
3331         clipRects.setOverflowClipRect(clipRects.fixedClipRect());
3332         clipRects.setFixed(true);
3333     }
3334     else if (renderer()->style()->position() == RelativePosition)
3335         clipRects.setPosClipRect(clipRects.overflowClipRect());
3336     else if (renderer()->style()->position() == AbsolutePosition)
3337         clipRects.setOverflowClipRect(clipRects.posClipRect());
3338 
3339     // Update the clip rects that will be passed to child layers.
3340     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
3341         // This layer establishes a clip of some kind.
3342         int x = 0;
3343         int y = 0;
3344         convertToLayerCoords(rootLayer, x, y);
3345         RenderView* view = renderer()->view();
3346         ASSERT(view);
3347         if (view && clipRects.fixed() && rootLayer->renderer() == view) {
3348             x -= view->frameView()->scrollXForFixedPosition();
3349             y -= view->frameView()->scrollYForFixedPosition();
3350         }
3351 
3352         if (renderer()->hasOverflowClip()) {
3353             IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy);
3354             clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
3355             if (renderer()->isPositioned() || renderer()->isRelPositioned())
3356                 clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
3357         }
3358         if (renderer()->hasClip()) {
3359             IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
3360             clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
3361             clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
3362             clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
3363         }
3364     }
3365 }
3366 
parentClipRects(const RenderLayer * rootLayer,ClipRects & clipRects,bool temporaryClipRects,OverlayScrollbarSizeRelevancy relevancy) const3367 void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
3368 {
3369     ASSERT(parent());
3370     if (temporaryClipRects) {
3371         parent()->calculateClipRects(rootLayer, clipRects, false, relevancy);
3372         return;
3373     }
3374 
3375     parent()->updateClipRects(rootLayer, relevancy);
3376     clipRects = *parent()->clipRects();
3377 }
3378 
backgroundClipRect(const RenderLayer * rootLayer,bool temporaryClipRects,OverlayScrollbarSizeRelevancy relevancy) const3379 IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
3380 {
3381     IntRect backgroundRect;
3382     if (parent()) {
3383         ClipRects parentRects;
3384         parentClipRects(rootLayer, parentRects, temporaryClipRects, relevancy);
3385         backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() :
3386                          (renderer()->isPositioned() ? parentRects.posClipRect() :
3387                                                        parentRects.overflowClipRect());
3388         RenderView* view = renderer()->view();
3389         ASSERT(view);
3390         if (view && parentRects.fixed() && rootLayer->renderer() == view)
3391             backgroundRect.move(view->frameView()->scrollXForFixedPosition(), view->frameView()->scrollYForFixedPosition());
3392     }
3393     return backgroundRect;
3394 }
3395 
calculateRects(const RenderLayer * rootLayer,const IntRect & paintDirtyRect,IntRect & layerBounds,IntRect & backgroundRect,IntRect & foregroundRect,IntRect & outlineRect,bool temporaryClipRects,OverlayScrollbarSizeRelevancy relevancy) const3396 void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
3397                                  IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects,
3398                                  OverlayScrollbarSizeRelevancy relevancy) const
3399 {
3400     if (rootLayer != this && parent()) {
3401         backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects, relevancy);
3402         backgroundRect.intersect(paintDirtyRect);
3403     } else
3404         backgroundRect = paintDirtyRect;
3405 
3406     foregroundRect = backgroundRect;
3407     outlineRect = backgroundRect;
3408 
3409     int x = 0;
3410     int y = 0;
3411     convertToLayerCoords(rootLayer, x, y);
3412     layerBounds = IntRect(x, y, width(), height());
3413 
3414     // Update the clip rects that will be passed to child layers.
3415     if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
3416         // This layer establishes a clip of some kind.
3417         if (renderer()->hasOverflowClip())
3418             foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y, relevancy));
3419         if (renderer()->hasClip()) {
3420             // Clip applies to *us* as well, so go ahead and update the damageRect.
3421             IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
3422             backgroundRect.intersect(newPosClip);
3423             foregroundRect.intersect(newPosClip);
3424             outlineRect.intersect(newPosClip);
3425         }
3426 
3427         // If we establish a clip at all, then go ahead and make sure our background
3428         // rect is intersected with our layer's bounds.
3429         // FIXME: This could be changed to just use generic visual overflow.
3430         // See https://bugs.webkit.org/show_bug.cgi?id=37467 for more information.
3431         if (const ShadowData* boxShadow = renderer()->style()->boxShadow()) {
3432             IntRect overflow = layerBounds;
3433             do {
3434                 if (boxShadow->style() == Normal) {
3435                     IntRect shadowRect = layerBounds;
3436                     shadowRect.move(boxShadow->x(), boxShadow->y());
3437                     shadowRect.inflate(boxShadow->blur() + boxShadow->spread());
3438                     overflow.unite(shadowRect);
3439                 }
3440 
3441                 boxShadow = boxShadow->next();
3442             } while (boxShadow);
3443             backgroundRect.intersect(overflow);
3444         } else
3445             backgroundRect.intersect(layerBounds);
3446     }
3447 }
3448 
childrenClipRect() const3449 IntRect RenderLayer::childrenClipRect() const
3450 {
3451     RenderView* renderView = renderer()->view();
3452     RenderLayer* clippingRootLayer = clippingRoot();
3453     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
3454     calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
3455     return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect)).enclosingBoundingBox();
3456 }
3457 
selfClipRect() const3458 IntRect RenderLayer::selfClipRect() const
3459 {
3460     RenderView* renderView = renderer()->view();
3461     RenderLayer* clippingRootLayer = clippingRoot();
3462     IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
3463     calculateRects(clippingRootLayer, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
3464     return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect)).enclosingBoundingBox();
3465 }
3466 
addBlockSelectionGapsBounds(const IntRect & bounds)3467 void RenderLayer::addBlockSelectionGapsBounds(const IntRect& bounds)
3468 {
3469     m_blockSelectionGapsBounds.unite(bounds);
3470 }
3471 
clearBlockSelectionGapsBounds()3472 void RenderLayer::clearBlockSelectionGapsBounds()
3473 {
3474     m_blockSelectionGapsBounds = IntRect();
3475     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3476         child->clearBlockSelectionGapsBounds();
3477 }
3478 
repaintBlockSelectionGaps()3479 void RenderLayer::repaintBlockSelectionGaps()
3480 {
3481     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3482         child->repaintBlockSelectionGaps();
3483 
3484     if (m_blockSelectionGapsBounds.isEmpty())
3485         return;
3486 
3487     IntRect rect = m_blockSelectionGapsBounds;
3488     rect.move(-scrolledContentOffset());
3489     if (renderer()->hasOverflowClip())
3490         rect.intersect(toRenderBox(renderer())->overflowClipRect(0, 0));
3491     if (renderer()->hasClip())
3492         rect.intersect(toRenderBox(renderer())->clipRect(0, 0));
3493     if (!rect.isEmpty())
3494         renderer()->repaintRectangle(rect);
3495 }
3496 
intersectsDamageRect(const IntRect & layerBounds,const IntRect & damageRect,const RenderLayer * rootLayer) const3497 bool RenderLayer::intersectsDamageRect(const IntRect& layerBounds, const IntRect& damageRect, const RenderLayer* rootLayer) const
3498 {
3499     // Always examine the canvas and the root.
3500     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
3501     // paints the root's background.
3502     if (renderer()->isRenderView() || renderer()->isRoot())
3503         return true;
3504 
3505     // If we aren't an inline flow, and our layer bounds do intersect the damage rect, then we
3506     // can go ahead and return true.
3507     RenderView* view = renderer()->view();
3508     ASSERT(view);
3509     if (view && !renderer()->isRenderInline()) {
3510         IntRect b = layerBounds;
3511         b.inflate(view->maximalOutlineSize());
3512         if (b.intersects(damageRect))
3513             return true;
3514     }
3515 
3516     // Otherwise we need to compute the bounding box of this single layer and see if it intersects
3517     // the damage rect.
3518     return boundingBox(rootLayer).intersects(damageRect);
3519 }
3520 
localBoundingBox() const3521 IntRect RenderLayer::localBoundingBox() const
3522 {
3523     // There are three special cases we need to consider.
3524     // (1) Inline Flows.  For inline flows we will create a bounding box that fully encompasses all of the lines occupied by the
3525     // inline.  In other words, if some <span> wraps to three lines, we'll create a bounding box that fully encloses the
3526     // line boxes of all three lines (including overflow on those lines).
3527     // (2) Left/Top Overflow.  The width/height of layers already includes right/bottom overflow.  However, in the case of left/top
3528     // overflow, we have to create a bounding box that will extend to include this overflow.
3529     // (3) Floats.  When a layer has overhanging floats that it paints, we need to make sure to include these overhanging floats
3530     // as part of our bounding box.  We do this because we are the responsible layer for both hit testing and painting those
3531     // floats.
3532     IntRect result;
3533     if (renderer()->isRenderInline())
3534         result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
3535     else if (renderer()->isTableRow()) {
3536         // Our bounding box is just the union of all of our cells' border/overflow rects.
3537         for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
3538             if (child->isTableCell()) {
3539                 IntRect bbox = toRenderBox(child)->borderBoxRect();
3540                 result.unite(bbox);
3541                 IntRect overflowRect = renderBox()->visualOverflowRect();
3542                 if (bbox != overflowRect)
3543                     result.unite(overflowRect);
3544             }
3545         }
3546     } else {
3547         RenderBox* box = renderBox();
3548         ASSERT(box);
3549         if (box->hasMask())
3550             result = box->maskClipRect();
3551         else {
3552             IntRect bbox = box->borderBoxRect();
3553             result = bbox;
3554             IntRect overflowRect = box->visualOverflowRect();
3555             if (bbox != overflowRect)
3556                 result.unite(overflowRect);
3557         }
3558     }
3559 
3560     RenderView* view = renderer()->view();
3561     ASSERT(view);
3562     if (view)
3563         result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
3564 
3565     return result;
3566 }
3567 
boundingBox(const RenderLayer * ancestorLayer) const3568 IntRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer) const
3569 {
3570     IntRect result = localBoundingBox();
3571     if (renderer()->isBox())
3572         renderBox()->flipForWritingMode(result);
3573     else
3574         renderer()->containingBlock()->flipForWritingMode(result);
3575     int deltaX = 0, deltaY = 0;
3576     convertToLayerCoords(ancestorLayer, deltaX, deltaY);
3577     result.move(deltaX, deltaY);
3578     return result;
3579 }
3580 
absoluteBoundingBox() const3581 IntRect RenderLayer::absoluteBoundingBox() const
3582 {
3583     return boundingBox(root());
3584 }
3585 
clearClipRectsIncludingDescendants()3586 void RenderLayer::clearClipRectsIncludingDescendants()
3587 {
3588     if (!m_clipRects)
3589         return;
3590 
3591     clearClipRects();
3592 
3593     for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
3594         l->clearClipRectsIncludingDescendants();
3595 }
3596 
clearClipRects()3597 void RenderLayer::clearClipRects()
3598 {
3599     if (m_clipRects) {
3600         m_clipRects->deref(renderer()->renderArena());
3601         m_clipRects = 0;
3602 #ifndef NDEBUG
3603         m_clipRectsRoot = 0;
3604 #endif
3605     }
3606 }
3607 
3608 #if USE(ACCELERATED_COMPOSITING)
ensureBacking()3609 RenderLayerBacking* RenderLayer::ensureBacking()
3610 {
3611     if (!m_backing)
3612         m_backing = adoptPtr(new RenderLayerBacking(this));
3613     return m_backing.get();
3614 }
3615 
clearBacking()3616 void RenderLayer::clearBacking()
3617 {
3618     m_backing.clear();
3619 }
3620 
hasCompositedMask() const3621 bool RenderLayer::hasCompositedMask() const
3622 {
3623     return m_backing && m_backing->hasMaskLayer();
3624 }
3625 
layerForHorizontalScrollbar() const3626 GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const
3627 {
3628     return m_backing ? m_backing->layerForHorizontalScrollbar() : 0;
3629 }
3630 
layerForVerticalScrollbar() const3631 GraphicsLayer* RenderLayer::layerForVerticalScrollbar() const
3632 {
3633     return m_backing ? m_backing->layerForVerticalScrollbar() : 0;
3634 }
3635 
layerForScrollCorner() const3636 GraphicsLayer* RenderLayer::layerForScrollCorner() const
3637 {
3638     return m_backing ? m_backing->layerForScrollCorner() : 0;
3639 }
3640 #endif
3641 
paintsWithTransform(PaintBehavior paintBehavior) const3642 bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
3643 {
3644 #if USE(ACCELERATED_COMPOSITING)
3645     bool paintsToWindow = !isComposited() || backing()->paintingGoesToWindow();
3646 #else
3647     bool paintsToWindow = true;
3648 #endif
3649     return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || paintsToWindow);
3650 }
3651 
setParent(RenderLayer * parent)3652 void RenderLayer::setParent(RenderLayer* parent)
3653 {
3654     if (parent == m_parent)
3655         return;
3656 
3657 #if USE(ACCELERATED_COMPOSITING)
3658     if (m_parent && !renderer()->documentBeingDestroyed())
3659         compositor()->layerWillBeRemoved(m_parent, this);
3660 #endif
3661 
3662     m_parent = parent;
3663 
3664 #if USE(ACCELERATED_COMPOSITING)
3665     if (m_parent && !renderer()->documentBeingDestroyed())
3666         compositor()->layerWasAdded(m_parent, this);
3667 #endif
3668 }
3669 
commonAncestor(RenderObject * obj1,RenderObject * obj2)3670 static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
3671 {
3672     if (!obj1 || !obj2)
3673         return 0;
3674 
3675     for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAncestor())
3676         for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hoverAncestor())
3677             if (currObj1 == currObj2)
3678                 return currObj1;
3679 
3680     return 0;
3681 }
3682 
updateHoverActiveState(const HitTestRequest & request,HitTestResult & result)3683 void RenderLayer::updateHoverActiveState(const HitTestRequest& request, HitTestResult& result)
3684 {
3685     // We don't update :hover/:active state when the result is marked as readOnly.
3686     if (request.readOnly())
3687         return;
3688 
3689     Document* doc = renderer()->document();
3690 
3691     Node* activeNode = doc->activeNode();
3692     if (activeNode && !request.active()) {
3693         // We are clearing the :active chain because the mouse has been released.
3694         for (RenderObject* curr = activeNode->renderer(); curr; curr = curr->parent()) {
3695             if (curr->node() && !curr->isText())
3696                 curr->node()->clearInActiveChain();
3697         }
3698         doc->setActiveNode(0);
3699     } else {
3700         Node* newActiveNode = result.innerNode();
3701         if (!activeNode && newActiveNode && request.active()) {
3702             // We are setting the :active chain and freezing it. If future moves happen, they
3703             // will need to reference this chain.
3704             for (RenderObject* curr = newActiveNode->renderer(); curr; curr = curr->parent()) {
3705                 if (curr->node() && !curr->isText()) {
3706                     curr->node()->setInActiveChain();
3707                 }
3708             }
3709             doc->setActiveNode(newActiveNode);
3710         }
3711     }
3712 
3713     // If the mouse is down and if this is a mouse move event, we want to restrict changes in
3714     // :hover/:active to only apply to elements that are in the :active chain that we froze
3715     // at the time the mouse went down.
3716     bool mustBeInActiveChain = request.active() && request.mouseMove();
3717 
3718     // Check to see if the hovered node has changed.  If not, then we don't need to
3719     // do anything.
3720     RefPtr<Node> oldHoverNode = doc->hoverNode();
3721     Node* newHoverNode = result.innerNode();
3722 
3723     // Update our current hover node.
3724     doc->setHoverNode(newHoverNode);
3725 
3726     // We have two different objects.  Fetch their renderers.
3727     RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
3728     RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
3729 
3730     // Locate the common ancestor render object for the two renderers.
3731     RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
3732 
3733     Vector<RefPtr<Node>, 32> nodesToRemoveFromChain;
3734     Vector<RefPtr<Node>, 32> nodesToAddToChain;
3735 
3736     if (oldHoverObj != newHoverObj) {
3737         // The old hover path only needs to be cleared up to (and not including) the common ancestor;
3738         for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) {
3739             if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
3740                 nodesToRemoveFromChain.append(curr->node());
3741         }
3742     }
3743 
3744     // Now set the hover state for our new object up to the root.
3745     for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
3746         if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->node()->inActiveChain()))
3747             nodesToAddToChain.append(curr->node());
3748     }
3749 
3750     size_t removeCount = nodesToRemoveFromChain.size();
3751     for (size_t i = 0; i < removeCount; ++i) {
3752         nodesToRemoveFromChain[i]->setActive(false);
3753         nodesToRemoveFromChain[i]->setHovered(false);
3754     }
3755 
3756     size_t addCount = nodesToAddToChain.size();
3757     for (size_t i = 0; i < addCount; ++i) {
3758         nodesToAddToChain[i]->setActive(request.active());
3759         nodesToAddToChain[i]->setHovered(true);
3760     }
3761 }
3762 
3763 // Helper for the sorting of layers by z-index.
compareZIndex(RenderLayer * first,RenderLayer * second)3764 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
3765 {
3766     return first->zIndex() < second->zIndex();
3767 }
3768 
dirtyZOrderLists()3769 void RenderLayer::dirtyZOrderLists()
3770 {
3771     if (m_posZOrderList)
3772         m_posZOrderList->clear();
3773     if (m_negZOrderList)
3774         m_negZOrderList->clear();
3775     m_zOrderListsDirty = true;
3776 
3777 #if USE(ACCELERATED_COMPOSITING)
3778     if (!renderer()->documentBeingDestroyed())
3779         compositor()->setCompositingLayersNeedRebuild();
3780 #endif
3781 }
3782 
dirtyStackingContextZOrderLists()3783 void RenderLayer::dirtyStackingContextZOrderLists()
3784 {
3785     RenderLayer* sc = stackingContext();
3786     if (sc)
3787         sc->dirtyZOrderLists();
3788 }
3789 
dirtyNormalFlowList()3790 void RenderLayer::dirtyNormalFlowList()
3791 {
3792     if (m_normalFlowList)
3793         m_normalFlowList->clear();
3794     m_normalFlowListDirty = true;
3795 
3796 #if USE(ACCELERATED_COMPOSITING)
3797     if (!renderer()->documentBeingDestroyed())
3798         compositor()->setCompositingLayersNeedRebuild();
3799 #endif
3800 }
3801 
updateZOrderLists()3802 void RenderLayer::updateZOrderLists()
3803 {
3804     if (!isStackingContext() || !m_zOrderListsDirty)
3805         return;
3806 
3807     for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
3808         if (!m_reflection || reflectionLayer() != child)
3809             child->collectLayers(m_posZOrderList, m_negZOrderList);
3810 
3811     // Sort the two lists.
3812     if (m_posZOrderList)
3813         std::stable_sort(m_posZOrderList->begin(), m_posZOrderList->end(), compareZIndex);
3814 
3815     if (m_negZOrderList)
3816         std::stable_sort(m_negZOrderList->begin(), m_negZOrderList->end(), compareZIndex);
3817 
3818     m_zOrderListsDirty = false;
3819 }
3820 
updateNormalFlowList()3821 void RenderLayer::updateNormalFlowList()
3822 {
3823     if (!m_normalFlowListDirty)
3824         return;
3825 
3826     for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
3827         // Ignore non-overflow layers and reflections.
3828         if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
3829             if (!m_normalFlowList)
3830                 m_normalFlowList = new Vector<RenderLayer*>;
3831             m_normalFlowList->append(child);
3832         }
3833     }
3834 
3835     m_normalFlowListDirty = false;
3836 }
3837 
collectLayers(Vector<RenderLayer * > * & posBuffer,Vector<RenderLayer * > * & negBuffer)3838 void RenderLayer::collectLayers(Vector<RenderLayer*>*& posBuffer, Vector<RenderLayer*>*& negBuffer)
3839 {
3840     updateVisibilityStatus();
3841 
3842     // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
3843     if ((m_hasVisibleContent || (m_hasVisibleDescendant && isStackingContext())) && !isNormalFlowOnly()) {
3844         // Determine which buffer the child should be in.
3845         Vector<RenderLayer*>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
3846 
3847         // Create the buffer if it doesn't exist yet.
3848         if (!buffer)
3849             buffer = new Vector<RenderLayer*>;
3850 
3851         // Append ourselves at the end of the appropriate buffer.
3852         buffer->append(this);
3853     }
3854 
3855     // Recur into our children to collect more layers, but only if we don't establish
3856     // a stacking context.
3857     if (m_hasVisibleDescendant && !isStackingContext()) {
3858         for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
3859             // Ignore reflections.
3860             if (!m_reflection || reflectionLayer() != child)
3861                 child->collectLayers(posBuffer, negBuffer);
3862         }
3863     }
3864 }
3865 
updateLayerListsIfNeeded()3866 void RenderLayer::updateLayerListsIfNeeded()
3867 {
3868     updateZOrderLists();
3869     updateNormalFlowList();
3870 }
3871 
updateCompositingAndLayerListsIfNeeded()3872 void RenderLayer::updateCompositingAndLayerListsIfNeeded()
3873 {
3874 #if USE(ACCELERATED_COMPOSITING)
3875     if (compositor()->inCompositingMode()) {
3876         if ((isStackingContext() && m_zOrderListsDirty) || m_normalFlowListDirty)
3877             compositor()->updateCompositingLayers(CompositingUpdateOnPaitingOrHitTest, this);
3878         return;
3879     }
3880 #endif
3881     updateLayerListsIfNeeded();
3882 }
3883 
repaintIncludingDescendants()3884 void RenderLayer::repaintIncludingDescendants()
3885 {
3886     renderer()->repaint();
3887     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
3888         curr->repaintIncludingDescendants();
3889 }
3890 
3891 #if USE(ACCELERATED_COMPOSITING)
setBackingNeedsRepaint()3892 void RenderLayer::setBackingNeedsRepaint()
3893 {
3894     ASSERT(isComposited());
3895     if (backing()->paintingGoesToWindow()) {
3896         // If we're trying to repaint the placeholder document layer, propagate the
3897         // repaint to the native view system.
3898         RenderView* view = renderer()->view();
3899         if (view)
3900             view->repaintViewRectangle(absoluteBoundingBox());
3901     } else
3902         backing()->setContentsNeedDisplay();
3903 }
3904 
setBackingNeedsRepaintInRect(const IntRect & r)3905 void RenderLayer::setBackingNeedsRepaintInRect(const IntRect& r)
3906 {
3907     // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here,
3908     // so assert but check that the layer is composited.
3909     ASSERT(isComposited());
3910     if (!isComposited() || backing()->paintingGoesToWindow()) {
3911         // If we're trying to repaint the placeholder document layer, propagate the
3912         // repaint to the native view system.
3913         IntRect absRect(r);
3914         int x = 0;
3915         int y = 0;
3916         convertToLayerCoords(root(), x, y);
3917         absRect.move(x, y);
3918 
3919         RenderView* view = renderer()->view();
3920         if (view)
3921             view->repaintViewRectangle(absRect);
3922     } else
3923         backing()->setContentsNeedDisplayInRect(r);
3924 }
3925 
3926 // Since we're only painting non-composited layers, we know that they all share the same repaintContainer.
repaintIncludingNonCompositingDescendants(RenderBoxModelObject * repaintContainer)3927 void RenderLayer::repaintIncludingNonCompositingDescendants(RenderBoxModelObject* repaintContainer)
3928 {
3929     renderer()->repaintUsingContainer(repaintContainer, renderer()->clippedOverflowRectForRepaint(repaintContainer));
3930 
3931     for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) {
3932         if (!curr->isComposited())
3933             curr->repaintIncludingNonCompositingDescendants(repaintContainer);
3934     }
3935 }
3936 #endif
3937 
shouldBeNormalFlowOnly() const3938 bool RenderLayer::shouldBeNormalFlowOnly() const
3939 {
3940     return (renderer()->hasOverflowClip()
3941                 || renderer()->hasReflection()
3942                 || renderer()->hasMask()
3943                 || renderer()->isVideo()
3944                 || renderer()->isEmbeddedObject()
3945                 || renderer()->isApplet()
3946                 || renderer()->isRenderIFrame()
3947                 || renderer()->style()->specifiesColumns())
3948             && !renderer()->isPositioned()
3949             && !renderer()->isRelPositioned()
3950             && !renderer()->hasTransform()
3951             && !isTransparent();
3952 }
3953 
isSelfPaintingLayer() const3954 bool RenderLayer::isSelfPaintingLayer() const
3955 {
3956     return !isNormalFlowOnly()
3957         || renderer()->hasReflection()
3958         || renderer()->hasMask()
3959         || renderer()->isTableRow()
3960         || renderer()->isVideo()
3961         || renderer()->isEmbeddedObject()
3962         || renderer()->isApplet()
3963         || renderer()->isRenderIFrame();
3964 }
3965 
styleChanged(StyleDifference diff,const RenderStyle * oldStyle)3966 void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle)
3967 {
3968     bool isNormalFlowOnly = shouldBeNormalFlowOnly();
3969     if (isNormalFlowOnly != m_isNormalFlowOnly) {
3970         m_isNormalFlowOnly = isNormalFlowOnly;
3971         RenderLayer* p = parent();
3972         if (p)
3973             p->dirtyNormalFlowList();
3974         dirtyStackingContextZOrderLists();
3975     }
3976 
3977     if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE && renderer()->isBox()) {
3978         if (!m_marquee)
3979             m_marquee = new RenderMarquee(this);
3980         m_marquee->updateMarqueeStyle();
3981     }
3982     else if (m_marquee) {
3983         delete m_marquee;
3984         m_marquee = 0;
3985     }
3986 
3987     if (!hasReflection() && m_reflection)
3988         removeReflection();
3989     else if (hasReflection()) {
3990         if (!m_reflection)
3991             createReflection();
3992         updateReflectionStyle();
3993     }
3994 
3995     // FIXME: Need to detect a swap from custom to native scrollbars (and vice versa).
3996     if (m_hBar)
3997         m_hBar->styleChanged();
3998     if (m_vBar)
3999         m_vBar->styleChanged();
4000 
4001     updateScrollCornerStyle();
4002     updateResizerStyle();
4003 
4004 #if USE(ACCELERATED_COMPOSITING)
4005     updateTransform();
4006 
4007     if (compositor()->updateLayerCompositingState(this))
4008         compositor()->setCompositingLayersNeedRebuild();
4009     else if (m_backing)
4010         m_backing->updateGraphicsLayerGeometry();
4011     else if (oldStyle && oldStyle->overflowX() != renderer()->style()->overflowX()) {
4012         if (stackingContext()->hasCompositingDescendant())
4013             compositor()->setCompositingLayersNeedRebuild();
4014     }
4015 
4016     if (m_backing && diff >= StyleDifferenceRepaint)
4017         m_backing->setContentsNeedDisplay();
4018 #else
4019     UNUSED_PARAM(diff);
4020 #endif
4021 }
4022 
updateScrollCornerStyle()4023 void RenderLayer::updateScrollCornerStyle()
4024 {
4025     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
4026     RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(SCROLLBAR_CORNER, actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
4027     if (corner) {
4028         if (!m_scrollCorner) {
4029             m_scrollCorner = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
4030             m_scrollCorner->setParent(renderer());
4031         }
4032         m_scrollCorner->setStyle(corner.release());
4033     } else if (m_scrollCorner) {
4034         m_scrollCorner->destroy();
4035         m_scrollCorner = 0;
4036     }
4037 }
4038 
updateResizerStyle()4039 void RenderLayer::updateResizerStyle()
4040 {
4041     RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();
4042     RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(RESIZER, actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
4043     if (resizer) {
4044         if (!m_resizer) {
4045             m_resizer = new (renderer()->renderArena()) RenderScrollbarPart(renderer()->document());
4046             m_resizer->setParent(renderer());
4047         }
4048         m_resizer->setStyle(resizer.release());
4049     } else if (m_resizer) {
4050         m_resizer->destroy();
4051         m_resizer = 0;
4052     }
4053 }
4054 
reflectionLayer() const4055 RenderLayer* RenderLayer::reflectionLayer() const
4056 {
4057     return m_reflection ? m_reflection->layer() : 0;
4058 }
4059 
createReflection()4060 void RenderLayer::createReflection()
4061 {
4062     ASSERT(!m_reflection);
4063     m_reflection = new (renderer()->renderArena()) RenderReplica(renderer()->document());
4064     m_reflection->setParent(renderer()); // We create a 1-way connection.
4065 }
4066 
removeReflection()4067 void RenderLayer::removeReflection()
4068 {
4069     if (!m_reflection->documentBeingDestroyed())
4070         m_reflection->removeLayers(this);
4071 
4072     m_reflection->setParent(0);
4073     m_reflection->destroy();
4074     m_reflection = 0;
4075 }
4076 
updateReflectionStyle()4077 void RenderLayer::updateReflectionStyle()
4078 {
4079     RefPtr<RenderStyle> newStyle = RenderStyle::create();
4080     newStyle->inheritFrom(renderer()->style());
4081 
4082     // Map in our transform.
4083     TransformOperations transform;
4084     switch (renderer()->style()->boxReflect()->direction()) {
4085         case ReflectionBelow:
4086             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
4087             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
4088             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
4089             break;
4090         case ReflectionAbove:
4091             transform.operations().append(ScaleTransformOperation::create(1.0, -1.0, ScaleTransformOperation::SCALE));
4092             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), Length(100., Percent), TransformOperation::TRANSLATE));
4093             transform.operations().append(TranslateTransformOperation::create(Length(0, Fixed), renderer()->style()->boxReflect()->offset(), TransformOperation::TRANSLATE));
4094             break;
4095         case ReflectionRight:
4096             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
4097             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
4098             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
4099             break;
4100         case ReflectionLeft:
4101             transform.operations().append(ScaleTransformOperation::create(-1.0, 1.0, ScaleTransformOperation::SCALE));
4102             transform.operations().append(TranslateTransformOperation::create(Length(100., Percent), Length(0, Fixed), TransformOperation::TRANSLATE));
4103             transform.operations().append(TranslateTransformOperation::create(renderer()->style()->boxReflect()->offset(), Length(0, Fixed), TransformOperation::TRANSLATE));
4104             break;
4105     }
4106     newStyle->setTransform(transform);
4107 
4108     // Map in our mask.
4109     newStyle->setMaskBoxImage(renderer()->style()->boxReflect()->mask());
4110 
4111     m_reflection->setStyle(newStyle.release());
4112 }
4113 
updateContentsScale(float scale)4114 void RenderLayer::updateContentsScale(float scale)
4115 {
4116 #if USE(ACCELERATED_COMPOSITING)
4117     if (m_backing)
4118         m_backing->updateContentsScale(scale);
4119 #endif
4120 }
4121 
4122 } // namespace WebCore
4123 
4124 #ifndef NDEBUG
showLayerTree(const WebCore::RenderLayer * layer)4125 void showLayerTree(const WebCore::RenderLayer* layer)
4126 {
4127     if (!layer)
4128         return;
4129 
4130     if (WebCore::Frame* frame = layer->renderer()->frame()) {
4131         WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState);
4132         fprintf(stderr, "%s\n", output.utf8().data());
4133     }
4134 }
4135 
showLayerTree(const WebCore::RenderObject * renderer)4136 void showLayerTree(const WebCore::RenderObject* renderer)
4137 {
4138     if (!renderer)
4139         return;
4140     showLayerTree(renderer->enclosingLayer());
4141 }
4142 #endif
4143