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