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