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