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