Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / RenderView.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #include "config.h"
22 #include "core/rendering/RenderView.h"
23
24 #include "core/dom/Document.h"
25 #include "core/dom/Element.h"
26 #include "core/frame/LocalFrame.h"
27 #include "core/html/HTMLDialogElement.h"
28 #include "core/html/HTMLFrameOwnerElement.h"
29 #include "core/html/HTMLIFrameElement.h"
30 #include "core/page/Page.h"
31 #include "core/rendering/ColumnInfo.h"
32 #include "core/rendering/FlowThreadController.h"
33 #include "core/rendering/GraphicsContextAnnotator.h"
34 #include "core/rendering/HitTestResult.h"
35 #include "core/rendering/RenderFlowThread.h"
36 #include "core/rendering/RenderGeometryMap.h"
37 #include "core/rendering/RenderLayer.h"
38 #include "core/rendering/RenderPart.h"
39 #include "core/rendering/RenderQuote.h"
40 #include "core/rendering/RenderSelectionInfo.h"
41 #include "core/rendering/compositing/CompositedLayerMapping.h"
42 #include "core/rendering/compositing/RenderLayerCompositor.h"
43 #include "core/svg/SVGDocumentExtensions.h"
44 #include "platform/RuntimeEnabledFeatures.h"
45 #include "platform/TraceEvent.h"
46 #include "platform/geometry/FloatQuad.h"
47 #include "platform/geometry/TransformState.h"
48 #include "platform/graphics/GraphicsContext.h"
49
50 namespace blink {
51
52 RenderView::RenderView(Document* document)
53     : RenderBlockFlow(document)
54     , m_frameView(document->view())
55     , m_selectionStart(nullptr)
56     , m_selectionEnd(nullptr)
57     , m_selectionStartPos(-1)
58     , m_selectionEndPos(-1)
59     , m_pageLogicalHeight(0)
60     , m_pageLogicalHeightChanged(false)
61     , m_layoutState(0)
62     , m_renderQuoteHead(nullptr)
63     , m_renderCounterCount(0)
64     , m_hitTestCount(0)
65 {
66     // init RenderObject attributes
67     setInline(false);
68
69     m_minPreferredLogicalWidth = 0;
70     m_maxPreferredLogicalWidth = 0;
71
72     setPreferredLogicalWidthsDirty(MarkOnlyThis);
73
74     setPositionState(AbsolutePosition); // to 0,0 :)
75 }
76
77 RenderView::~RenderView()
78 {
79 }
80
81 void RenderView::trace(Visitor* visitor)
82 {
83     visitor->trace(m_selectionStart);
84     visitor->trace(m_selectionEnd);
85     visitor->trace(m_renderQuoteHead);
86     RenderBlockFlow::trace(visitor);
87 }
88
89 bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
90 {
91     return hitTest(request, result.hitTestLocation(), result);
92 }
93
94 bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result)
95 {
96     TRACE_EVENT0("blink", "RenderView::hitTest");
97     m_hitTestCount++;
98
99     // We have to recursively update layout/style here because otherwise, when the hit test recurses
100     // into a child document, it could trigger a layout on the parent document, which can destroy RenderLayers
101     // that are higher up in the call stack, leading to crashes.
102     // Note that Document::updateLayout calls its parent's updateLayout.
103     // FIXME: It should be the caller's responsibility to ensure an up-to-date layout.
104     frameView()->updateLayoutAndStyleIfNeededRecursive();
105     return layer()->hitTest(request, location, result);
106 }
107
108 void RenderView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit, LogicalExtentComputedValues& computedValues) const
109 {
110     computedValues.m_extent = (!shouldUsePrintingLayout() && m_frameView) ? LayoutUnit(viewLogicalHeight()) : logicalHeight;
111 }
112
113 void RenderView::updateLogicalWidth()
114 {
115     if (!shouldUsePrintingLayout() && m_frameView)
116         setLogicalWidth(viewLogicalWidth());
117 }
118
119 LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType heightType) const
120 {
121     // If we have columns, then the available logical height is reduced to the column height.
122     if (hasColumns())
123         return columnInfo()->columnHeight();
124     return RenderBlockFlow::availableLogicalHeight(heightType);
125 }
126
127 bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
128 {
129     return child->isBox();
130 }
131
132 static bool canCenterDialog(const RenderStyle* style)
133 {
134     return (style->position() == AbsolutePosition || style->position() == FixedPosition) && style->hasAutoTopAndBottom();
135 }
136
137 void RenderView::positionDialog(RenderBox* box)
138 {
139     HTMLDialogElement* dialog = toHTMLDialogElement(box->node());
140     if (dialog->centeringMode() == HTMLDialogElement::NotCentered)
141         return;
142     if (dialog->centeringMode() == HTMLDialogElement::Centered) {
143         if (canCenterDialog(box->style()))
144             box->setY(dialog->centeredPosition());
145         return;
146     }
147
148     ASSERT(dialog->centeringMode() == HTMLDialogElement::NeedsCentering);
149     if (!canCenterDialog(box->style())) {
150         dialog->setNotCentered();
151         return;
152     }
153     FrameView* frameView = document().view();
154     LayoutUnit top = (box->style()->position() == FixedPosition) ? 0 : frameView->scrollOffset().height();
155     int visibleHeight = frameView->visibleContentRect(IncludeScrollbars).height();
156     if (box->height() < visibleHeight)
157         top += (visibleHeight - box->height()) / 2;
158     box->setY(top);
159     dialog->setCentered(top);
160 }
161
162 void RenderView::positionDialogs()
163 {
164     TrackedRendererListHashSet* positionedDescendants = positionedObjects();
165     if (!positionedDescendants)
166         return;
167     TrackedRendererListHashSet::iterator end = positionedDescendants->end();
168     for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
169         RenderBox* box = *it;
170         if (isHTMLDialogElement(box->node()))
171             positionDialog(box);
172     }
173 }
174
175 void RenderView::layoutContent()
176 {
177     ASSERT(needsLayout());
178
179     RenderBlockFlow::layout();
180
181     if (RuntimeEnabledFeatures::dialogElementEnabled())
182         positionDialogs();
183
184 #if ENABLE(ASSERT)
185     checkLayoutState();
186 #endif
187 }
188
189 #if ENABLE(ASSERT)
190 void RenderView::checkLayoutState()
191 {
192     ASSERT(!m_layoutState->next());
193 }
194 #endif
195
196 bool RenderView::shouldDoFullPaintInvalidationForNextLayout() const
197 {
198     // It's hard to predict here which of full paint invalidation or per-descendant paint invalidation costs less.
199     // For vertical writing mode or width change it's more likely that per-descendant paint invalidation
200     // eventually turns out to be full paint invalidation but with the cost to handle more layout states
201     // and discrete paint invalidation rects, so marking full paint invalidation here is more likely to cost less.
202     // Otherwise, per-descendant paint invalidation is more likely to avoid unnecessary full paint invalidation.
203
204     if (shouldUsePrintingLayout())
205         return true;
206
207     if (!style()->isHorizontalWritingMode() || width() != viewWidth())
208         return true;
209
210     if (height() != viewHeight()) {
211         if (RenderObject* backgroundRenderer = this->backgroundRenderer()) {
212             // When background-attachment is 'fixed', we treat the viewport (instead of the 'root'
213             // i.e. html or body) as the background positioning area, and we should full paint invalidation
214             // viewport resize if the background image is not composited and needs full paint invalidation on
215             // background positioning area resize.
216             if (!m_compositor || !m_compositor->needsFixedRootBackgroundLayer(layer())) {
217                 if (backgroundRenderer->style()->hasFixedBackgroundImage()
218                     && mustInvalidateFillLayersPaintOnHeightChange(backgroundRenderer->style()->backgroundLayers()))
219                 return true;
220             }
221         }
222     }
223
224     return false;
225 }
226
227 void RenderView::layout()
228 {
229     if (!document().paginated())
230         setPageLogicalHeight(0);
231
232     if (shouldUsePrintingLayout())
233         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
234
235     SubtreeLayoutScope layoutScope(*this);
236
237     // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
238     bool relayoutChildren = !shouldUsePrintingLayout() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
239     if (relayoutChildren) {
240         layoutScope.setChildNeedsLayout(this);
241         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
242             if (child->isSVGRoot())
243                 continue;
244
245             if ((child->isBox() && toRenderBox(child)->hasRelativeLogicalHeight())
246                     || child->style()->logicalHeight().isPercent()
247                     || child->style()->logicalMinHeight().isPercent()
248                     || child->style()->logicalMaxHeight().isPercent())
249                 layoutScope.setChildNeedsLayout(child);
250         }
251
252         if (document().svgExtensions())
253             document().accessSVGExtensions().invalidateSVGRootsWithRelativeLengthDescendents(&layoutScope);
254     }
255
256     ASSERT(!m_layoutState);
257     if (!needsLayout())
258         return;
259
260     LayoutState rootLayoutState(pageLogicalHeight(), pageLogicalHeightChanged(), *this);
261
262     m_pageLogicalHeightChanged = false;
263
264     layoutContent();
265
266 #if ENABLE(ASSERT)
267     checkLayoutState();
268 #endif
269     clearNeedsLayout();
270 }
271
272 void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
273 {
274     ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == static_cast<bool>(mode & IsFixed));
275
276     if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) {
277         TransformationMatrix t;
278         getTransformFromContainer(0, LayoutSize(), t);
279         transformState.applyTransform(t);
280     }
281
282     if (mode & IsFixed && m_frameView)
283         transformState.move(m_frameView->scrollOffsetForFixedPosition());
284
285     if (repaintContainer == this)
286         return;
287
288     if (mode & TraverseDocumentBoundaries) {
289         if (RenderObject* parentDocRenderer = frame()->ownerRenderer()) {
290             transformState.move(-frame()->view()->scrollOffset());
291             if (parentDocRenderer->isBox())
292                 transformState.move(toLayoutSize(toRenderBox(parentDocRenderer)->contentBoxRect().location()));
293             parentDocRenderer->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed, paintInvalidationState);
294             return;
295         }
296     }
297
298     // If a container was specified, and was not 0 or the RenderView,
299     // then we should have found it by now.
300     ASSERT_ARG(repaintContainer, !repaintContainer);
301 }
302
303 const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
304 {
305     LayoutSize offsetForFixedPosition;
306     LayoutSize offset;
307     RenderObject* container = 0;
308
309     if (m_frameView)
310         offsetForFixedPosition = m_frameView->scrollOffsetForFixedPosition();
311
312     if (geometryMap.mapCoordinatesFlags() & TraverseDocumentBoundaries) {
313         if (RenderPart* parentDocRenderer = frame()->ownerRenderer()) {
314             offset = -m_frameView->scrollOffset();
315             offset += toLayoutSize(parentDocRenderer->contentBoxRect().location());
316             container = parentDocRenderer;
317         }
318     }
319
320     // If a container was specified, and was not 0 or the RenderView, then we
321     // should have found it by now unless we're traversing to a parent document.
322     ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this || container);
323
324     if ((!ancestorToStopAt || container) && shouldUseTransformFromContainer(container)) {
325         TransformationMatrix t;
326         getTransformFromContainer(container, LayoutSize(), t);
327         geometryMap.push(this, t, false, false, false, true, offsetForFixedPosition);
328     } else {
329         geometryMap.push(this, offset, false, false, false, false, offsetForFixedPosition);
330     }
331
332     return container;
333 }
334
335 void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
336 {
337     if (mode & IsFixed && m_frameView)
338         transformState.move(m_frameView->scrollOffsetForFixedPosition());
339
340     if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
341         TransformationMatrix t;
342         getTransformFromContainer(0, LayoutSize(), t);
343         transformState.applyTransform(t);
344     }
345 }
346
347 void RenderView::computeSelfHitTestRects(Vector<LayoutRect>& rects, const LayoutPoint&) const
348 {
349     // Record the entire size of the contents of the frame. Note that we don't just
350     // use the viewport size (containing block) here because we want to ensure this includes
351     // all children (so we can avoid walking them explicitly).
352     rects.append(LayoutRect(LayoutPoint::zero(), frameView()->contentsSize()));
353 }
354
355 void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
356 {
357     // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
358     ASSERT(!needsLayout());
359     // RenderViews should never be called to paint with an offset not on device pixels.
360     ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
361
362     ANNOTATE_GRAPHICS_CONTEXT(paintInfo, this);
363
364     // This avoids painting garbage between columns if there is a column gap.
365     if (m_frameView && style()->isOverflowPaged())
366         paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor());
367
368     paintObject(paintInfo, paintOffset);
369 }
370
371 static inline bool rendererObscuresBackground(RenderBox* rootBox)
372 {
373     ASSERT(rootBox);
374     RenderStyle* style = rootBox->style();
375     if (style->visibility() != VISIBLE
376         || style->opacity() != 1
377         || style->hasFilter()
378         || style->hasTransform())
379         return false;
380
381     if (rootBox->compositingState() == PaintsIntoOwnBacking)
382         return false;
383
384     const RenderObject* rootRenderer = rootBox->rendererForRootBackground();
385     if (rootRenderer->style()->backgroundClip() == TextFillBox)
386         return false;
387
388     return true;
389 }
390
391 bool RenderView::rootFillsViewportBackground(RenderBox* rootBox) const
392 {
393     ASSERT(rootBox);
394     // CSS Boxes always fill the viewport background (see paintRootBoxFillLayers)
395     if (!rootBox->isSVG())
396         return true;
397
398     return rootBox->frameRect().contains(frameRect());
399 }
400
401 void RenderView::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint&)
402 {
403     if (document().ownerElement() || !view())
404         return;
405
406     if (paintInfo.skipRootBackground())
407         return;
408
409     bool shouldPaintBackground = true;
410     Node* documentElement = document().documentElement();
411     if (RenderBox* rootBox = documentElement ? toRenderBox(documentElement->renderer()) : 0)
412         shouldPaintBackground = !rootFillsViewportBackground(rootBox) || !rendererObscuresBackground(rootBox);
413
414     // If painting will entirely fill the view, no need to fill the background.
415     if (!shouldPaintBackground)
416         return;
417
418     // This code typically only executes if the root element's visibility has been set to hidden,
419     // if there is a transform on the <html>, or if there is a page scale factor less than 1.
420     // Only fill with the base background color (typically white) if we're the root document,
421     // since iframes/frames with no background in the child document should show the parent's background.
422     if (!frameView()->isTransparent()) {
423         Color baseColor = frameView()->baseBackgroundColor();
424         if (baseColor.alpha()) {
425             CompositeOperator previousOperator = paintInfo.context->compositeOperation();
426             paintInfo.context->setCompositeOperation(CompositeCopy);
427             paintInfo.context->fillRect(paintInfo.rect, baseColor);
428             paintInfo.context->setCompositeOperation(previousOperator);
429         } else {
430             paintInfo.context->clearRect(paintInfo.rect);
431         }
432     }
433 }
434
435 void RenderView::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvalidationState)
436 {
437     ASSERT(!needsLayout());
438
439     // We specifically need to repaint the viewRect since other renderers
440     // short-circuit on full-repaint.
441     if (doingFullPaintInvalidation() && !viewRect().isEmpty())
442         invalidatePaintForRectangle(viewRect());
443
444     RenderBlock::invalidateTreeIfNeeded(paintInvalidationState);
445 }
446
447 void RenderView::invalidatePaintForRectangle(const LayoutRect& paintInvalidationRect) const
448 {
449     ASSERT(!paintInvalidationRect.isEmpty());
450
451     if (document().printing() || !m_frameView)
452         return;
453
454     // We always just invalidate the root view, since we could be an iframe that is clipped out
455     // or even invisible.
456     Element* owner = document().ownerElement();
457     if (layer()->compositingState() == PaintsIntoOwnBacking) {
458         layer()->paintInvalidator().setBackingNeedsRepaintInRect(paintInvalidationRect);
459     } else if (!owner) {
460         m_frameView->contentRectangleForPaintInvalidation(pixelSnappedIntRect(paintInvalidationRect));
461     } else if (RenderBox* obj = owner->renderBox()) {
462         // Intersect the viewport with the paint invalidation rect.
463         LayoutRect viewRectangle = viewRect();
464         LayoutRect rectToInvalidate = intersection(paintInvalidationRect, viewRectangle);
465
466         // Adjust for scroll offset of the view.
467         rectToInvalidate.moveBy(-viewRectangle.location());
468
469         // Adjust for frame border.
470         rectToInvalidate.moveBy(obj->contentBoxRect().location());
471         obj->invalidatePaintRectangle(rectToInvalidate);
472     }
473 }
474
475 void RenderView::invalidatePaintForViewAndCompositedLayers()
476 {
477     paintInvalidationForWholeRenderer();
478
479     // The only way we know how to hit these ASSERTS below this point is via the Chromium OS login screen.
480     DisableCompositingQueryAsserts disabler;
481
482     if (compositor()->inCompositingMode())
483         compositor()->fullyInvalidatePaint();
484 }
485
486 void RenderView::mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect& rect, ViewportConstrainedPosition viewportConstraint, const PaintInvalidationState*) const
487 {
488     // If a container was specified, and was not 0 or the RenderView,
489     // then we should have found it by now.
490     ASSERT_ARG(paintInvalidationContainer, !paintInvalidationContainer || paintInvalidationContainer == this);
491
492     if (document().printing())
493         return;
494
495     if (style()->isFlippedBlocksWritingMode()) {
496         // We have to flip by hand since the view's logical height has not been determined.  We
497         // can use the viewport width and height.
498         if (style()->isHorizontalWritingMode())
499             rect.setY(viewHeight() - rect.maxY());
500         else
501             rect.setX(viewWidth() - rect.maxX());
502     }
503
504     ASSERT(viewportConstraint != ViewportConstraintDoesNotMatter);
505     if (viewportConstraint == IsFixedPosition && m_frameView) {
506         rect.move(m_frameView->scrollOffsetForFixedPosition());
507         // If we have a pending scroll, invalidate the previous scroll position.
508         if (!m_frameView->pendingScrollDelta().isZero()) {
509             rect.move(-m_frameView->pendingScrollDelta());
510         }
511     }
512
513     // Apply our transform if we have one (because of full page zooming).
514     if (!paintInvalidationContainer && layer() && layer()->transform())
515         rect = layer()->transform()->mapRect(rect);
516 }
517
518 void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
519 {
520     rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));
521 }
522
523 void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
524 {
525     if (wasFixed)
526         *wasFixed = false;
527     quads.append(FloatRect(FloatPoint(), layer()->size()));
528 }
529
530 static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
531 {
532     if (!object)
533         return 0;
534
535     RenderObject* child = object->childAt(offset);
536     return child ? child : object->nextInPreOrderAfterChildren();
537 }
538
539 IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
540 {
541     typedef WillBeHeapHashMap<RawPtrWillBeMember<RenderObject>, OwnPtrWillBeMember<RenderSelectionInfo> > SelectionMap;
542     SelectionMap selectedObjects;
543
544     RenderObject* os = m_selectionStart;
545     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
546     while (os && os != stop) {
547         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
548             // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
549             selectedObjects.set(os, adoptPtrWillBeNoop(new RenderSelectionInfo(os, clipToVisibleContent)));
550             RenderBlock* cb = os->containingBlock();
551             while (cb && !cb->isRenderView()) {
552                 OwnPtrWillBeMember<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).storedValue->value;
553                 if (blockInfo)
554                     break;
555                 blockInfo = adoptPtrWillBeNoop(new RenderSelectionInfo(cb, clipToVisibleContent));
556                 cb = cb->containingBlock();
557             }
558         }
559
560         os = os->nextInPreOrder();
561     }
562
563     // Now create a single bounding box rect that encloses the whole selection.
564     LayoutRect selRect;
565     SelectionMap::iterator end = selectedObjects.end();
566     for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
567         RenderSelectionInfo* info = i->value.get();
568         // RenderSelectionInfo::rect() is in the coordinates of the paintInvalidationContainer, so map to page coordinates.
569         LayoutRect currRect = info->rect();
570         if (const RenderLayerModelObject* paintInvalidationContainer = info->repaintContainer()) {
571             FloatQuad absQuad = paintInvalidationContainer->localToAbsoluteQuad(FloatRect(currRect));
572             currRect = absQuad.enclosingBoundingBox();
573         }
574         selRect.unite(currRect);
575     }
576     return pixelSnappedIntRect(selRect);
577 }
578
579 void RenderView::invalidatePaintForSelection() const
580 {
581     HashSet<RenderBlock*> processedBlocks;
582
583     RenderObject* end = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
584     for (RenderObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
585         if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
586             continue;
587         if (o->selectionState() == SelectionNone)
588             continue;
589
590         RenderSelectionInfo(o, true).repaint();
591
592         // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
593         for (RenderBlock* block = o->containingBlock(); block && !block->isRenderView(); block = block->containingBlock()) {
594             if (!processedBlocks.add(block).isNewEntry)
595                 break;
596             RenderSelectionInfo(block, true).repaint();
597         }
598     }
599 }
600
601 // When exploring the RenderTree looking for the nodes involved in the Selection, sometimes it's
602 // required to change the traversing direction because the "start" position is below the "end" one.
603 static inline RenderObject* getNextOrPrevRenderObjectBasedOnDirection(const RenderObject* o, const RenderObject* stop, bool& continueExploring, bool& exploringBackwards)
604 {
605     RenderObject* next;
606     if (exploringBackwards) {
607         next = o->previousInPreOrder();
608         continueExploring = next && !(next)->isRenderView();
609     } else {
610         next = o->nextInPreOrder();
611         continueExploring = next && next != stop;
612         exploringBackwards = !next && (next != stop);
613         if (exploringBackwards) {
614             next = stop->previousInPreOrder();
615             continueExploring = next && !next->isRenderView();
616         }
617     }
618
619     return next;
620 }
621
622 void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
623 {
624     // This code makes no assumptions as to if the rendering tree is up to date or not
625     // and will not try to update it. Currently clearSelection calls this
626     // (intentionally) without updating the rendering tree as it doesn't care.
627     // Other callers may want to force recalc style before calling this.
628
629     // Make sure both our start and end objects are defined.
630     // Check www.msnbc.com and try clicking around to find the case where this happened.
631     if ((start && !end) || (end && !start))
632         return;
633
634     // Just return if the selection hasn't changed.
635     if (m_selectionStart == start && m_selectionStartPos == startPos &&
636         m_selectionEnd == end && m_selectionEndPos == endPos)
637         return;
638
639     // Record the old selected objects.  These will be used later
640     // when we compare against the new selected objects.
641     int oldStartPos = m_selectionStartPos;
642     int oldEndPos = m_selectionEndPos;
643
644     // Objects each have a single selection rect to examine.
645     typedef WillBeHeapHashMap<RawPtrWillBeMember<RenderObject>, OwnPtrWillBeMember<RenderSelectionInfo> > SelectedObjectMap;
646     SelectedObjectMap oldSelectedObjects;
647     SelectedObjectMap newSelectedObjects;
648
649     // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
650     // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
651     // the union of those rects might remain the same even when changes have occurred.
652     typedef WillBeHeapHashMap<RawPtrWillBeMember<RenderBlock>, OwnPtrWillBeMember<RenderBlockSelectionInfo> > SelectedBlockMap;
653     SelectedBlockMap oldSelectedBlocks;
654     SelectedBlockMap newSelectedBlocks;
655
656     RenderObject* os = m_selectionStart;
657     RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
658     bool exploringBackwards = false;
659     bool continueExploring = os && (os != stop);
660     while (continueExploring) {
661         if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
662             // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
663             oldSelectedObjects.set(os, adoptPtrWillBeNoop(new RenderSelectionInfo(os, true)));
664             if (blockRepaintMode == RepaintNewXOROld) {
665                 RenderBlock* cb = os->containingBlock();
666                 while (cb && !cb->isRenderView()) {
667                     OwnPtrWillBeMember<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).storedValue->value;
668                     if (blockInfo)
669                         break;
670                     blockInfo = adoptPtrWillBeNoop(new RenderBlockSelectionInfo(cb));
671                     cb = cb->containingBlock();
672                 }
673             }
674         }
675
676         os = getNextOrPrevRenderObjectBasedOnDirection(os, stop, continueExploring, exploringBackwards);
677     }
678
679     // Now clear the selection.
680     SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
681     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
682         i->key->setSelectionStateIfNeeded(SelectionNone);
683
684     // set selection start and end
685     m_selectionStart = start;
686     m_selectionStartPos = startPos;
687     m_selectionEnd = end;
688     m_selectionEndPos = endPos;
689
690     // Update the selection status of all objects between m_selectionStart and m_selectionEnd
691     if (start && start == end)
692         start->setSelectionStateIfNeeded(SelectionBoth);
693     else {
694         if (start)
695             start->setSelectionStateIfNeeded(SelectionStart);
696         if (end)
697             end->setSelectionStateIfNeeded(SelectionEnd);
698     }
699
700     RenderObject* o = start;
701     stop = rendererAfterPosition(end, endPos);
702
703     while (o && o != stop) {
704         if (o != start && o != end && o->canBeSelectionLeaf())
705             o->setSelectionStateIfNeeded(SelectionInside);
706         o = o->nextInPreOrder();
707     }
708
709     if (blockRepaintMode != RepaintNothing)
710         layer()->clearBlockSelectionGapsBounds();
711
712     // Now that the selection state has been updated for the new objects, walk them again and
713     // put them in the new objects list.
714     o = start;
715     exploringBackwards = false;
716     continueExploring = o && (o != stop);
717     while (continueExploring) {
718         if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
719             newSelectedObjects.set(o, adoptPtrWillBeNoop(new RenderSelectionInfo(o, true)));
720             RenderBlock* cb = o->containingBlock();
721             while (cb && !cb->isRenderView()) {
722                 OwnPtrWillBeMember<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).storedValue->value;
723                 if (blockInfo)
724                     break;
725                 blockInfo = adoptPtrWillBeNoop(new RenderBlockSelectionInfo(cb));
726                 cb = cb->containingBlock();
727             }
728         }
729
730         o = getNextOrPrevRenderObjectBasedOnDirection(o, stop, continueExploring, exploringBackwards);
731     }
732
733     if (!m_frameView || blockRepaintMode == RepaintNothing)
734         return;
735
736     // Have any of the old selected objects changed compared to the new selection?
737     for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
738         RenderObject* obj = i->key;
739         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
740         RenderSelectionInfo* oldInfo = i->value.get();
741         if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
742             (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
743             (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
744             oldInfo->repaint();
745             if (newInfo) {
746                 newInfo->repaint();
747                 newSelectedObjects.remove(obj);
748             }
749         }
750     }
751
752     // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
753     SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
754     for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
755         i->value->repaint();
756
757     // Have any of the old blocks changed?
758     SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
759     for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
760         RenderBlock* block = i->key;
761         RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
762         RenderBlockSelectionInfo* oldInfo = i->value.get();
763         if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
764             oldInfo->repaint();
765             if (newInfo) {
766                 newInfo->repaint();
767                 newSelectedBlocks.remove(block);
768             }
769         }
770     }
771
772     // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
773     SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
774     for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
775         i->value->repaint();
776 }
777
778 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const
779 {
780     startRenderer = m_selectionStart;
781     startOffset = m_selectionStartPos;
782     endRenderer = m_selectionEnd;
783     endOffset = m_selectionEndPos;
784 }
785
786 void RenderView::clearSelection()
787 {
788     layer()->invalidatePaintForBlockSelectionGaps();
789     setSelection(0, -1, 0, -1, RepaintNewMinusOld);
790 }
791
792 void RenderView::selectionStartEnd(int& startPos, int& endPos) const
793 {
794     startPos = m_selectionStartPos;
795     endPos = m_selectionEndPos;
796 }
797
798 bool RenderView::shouldUsePrintingLayout() const
799 {
800     if (!document().printing() || !m_frameView)
801         return false;
802     return m_frameView->frame().shouldUsePrintingLayout();
803 }
804
805 LayoutRect RenderView::viewRect() const
806 {
807     if (shouldUsePrintingLayout())
808         return LayoutRect(LayoutPoint(), size());
809     if (m_frameView)
810         return m_frameView->visibleContentRect();
811     return LayoutRect();
812 }
813
814 IntRect RenderView::unscaledDocumentRect() const
815 {
816     LayoutRect overflowRect(layoutOverflowRect());
817     flipForWritingMode(overflowRect);
818     return pixelSnappedIntRect(overflowRect);
819 }
820
821 bool RenderView::rootBackgroundIsEntirelyFixed() const
822 {
823     if (RenderObject* backgroundRenderer = this->backgroundRenderer())
824         return backgroundRenderer->hasEntirelyFixedBackground();
825     return false;
826 }
827
828 RenderObject* RenderView::backgroundRenderer() const
829 {
830     if (Element* documentElement = document().documentElement()) {
831         if (RenderObject* rootObject = documentElement->renderer())
832             return rootObject->rendererForRootBackground();
833     }
834     return 0;
835 }
836
837 LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
838 {
839     if (!hasColumns())
840         return unscaledDocumentRect();
841
842     ColumnInfo* columnInfo = this->columnInfo();
843     LayoutRect backgroundRect(0, 0, columnInfo->desiredColumnWidth(), columnInfo->columnHeight() * columnInfo->columnCount());
844     if (!isHorizontalWritingMode())
845         backgroundRect = backgroundRect.transposedRect();
846     backgroundRenderer->flipForWritingMode(backgroundRect);
847
848     return backgroundRect;
849 }
850
851 IntRect RenderView::documentRect() const
852 {
853     FloatRect overflowRect(unscaledDocumentRect());
854     if (hasTransform())
855         overflowRect = layer()->currentTransform().mapRect(overflowRect);
856     return IntRect(overflowRect);
857 }
858
859 int RenderView::viewHeight(IncludeScrollbarsInRect scrollbarInclusion) const
860 {
861     int height = 0;
862     if (!shouldUsePrintingLayout() && m_frameView)
863         height = m_frameView->layoutSize(scrollbarInclusion).height();
864
865     return height;
866 }
867
868 int RenderView::viewWidth(IncludeScrollbarsInRect scrollbarInclusion) const
869 {
870     int width = 0;
871     if (!shouldUsePrintingLayout() && m_frameView)
872         width = m_frameView->layoutSize(scrollbarInclusion).width();
873
874     return width;
875 }
876
877 int RenderView::viewLogicalHeight() const
878 {
879     return style()->isHorizontalWritingMode() ? viewHeight(ExcludeScrollbars) : viewWidth(ExcludeScrollbars);
880 }
881
882 LayoutUnit RenderView::viewLogicalHeightForPercentages() const
883 {
884     if (shouldUsePrintingLayout())
885         return pageLogicalHeight();
886     return viewLogicalHeight();
887 }
888
889 float RenderView::zoomFactor() const
890 {
891     return m_frameView->frame().pageZoomFactor();
892 }
893
894 void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
895 {
896     if (result.innerNode())
897         return;
898
899     Node* node = document().documentElement();
900     if (node) {
901         result.setInnerNode(node);
902         if (!result.innerNonSharedNode())
903             result.setInnerNonSharedNode(node);
904
905         LayoutPoint adjustedPoint = point;
906         offsetForContents(adjustedPoint);
907
908         result.setLocalPoint(adjustedPoint);
909     }
910 }
911
912 bool RenderView::usesCompositing() const
913 {
914     return m_compositor && m_compositor->staleInCompositingMode();
915 }
916
917 RenderLayerCompositor* RenderView::compositor()
918 {
919     if (!m_compositor)
920         m_compositor = adoptPtr(new RenderLayerCompositor(*this));
921
922     return m_compositor.get();
923 }
924
925 void RenderView::setIsInWindow(bool isInWindow)
926 {
927     if (m_compositor)
928         m_compositor->setIsInWindow(isInWindow);
929 }
930
931 FlowThreadController* RenderView::flowThreadController()
932 {
933     if (!m_flowThreadController)
934         m_flowThreadController = FlowThreadController::create();
935
936     return m_flowThreadController.get();
937 }
938
939 void RenderView::pushLayoutState(LayoutState& layoutState)
940 {
941     if (m_flowThreadController) {
942         RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
943         if (currentFlowThread)
944             currentFlowThread->pushFlowThreadLayoutState(layoutState.renderer());
945     }
946     m_layoutState = &layoutState;
947 }
948
949 void RenderView::popLayoutState()
950 {
951     ASSERT(m_layoutState);
952     m_layoutState = m_layoutState->next();
953     if (!m_flowThreadController)
954         return;
955
956     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
957     if (!currentFlowThread)
958         return;
959
960     currentFlowThread->popFlowThreadLayoutState();
961 }
962
963 IntervalArena* RenderView::intervalArena()
964 {
965     if (!m_intervalArena)
966         m_intervalArena = IntervalArena::create();
967     return m_intervalArena.get();
968 }
969
970 bool RenderView::backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const
971 {
972     // FIXME: Remove this main frame check. Same concept applies to subframes too.
973     if (!frame()->isMainFrame())
974         return false;
975
976     return m_frameView->hasOpaqueBackground();
977 }
978
979 double RenderView::layoutViewportWidth() const
980 {
981     float scale = m_frameView ? m_frameView->frame().pageZoomFactor() : 1;
982     return viewWidth(IncludeScrollbars) / scale;
983 }
984
985 double RenderView::layoutViewportHeight() const
986 {
987     float scale = m_frameView ? m_frameView->frame().pageZoomFactor() : 1;
988     return viewHeight(IncludeScrollbars) / scale;
989 }
990
991 } // namespace blink