/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/layout/LayoutView.h"

#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/editing/FrameSelection.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLIFrameElement.h"
#include "core/html/HTMLVideoElement.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutFlowThread.h"
#include "core/layout/LayoutGeometryMap.h"
#include "core/layout/LayoutMedia.h"
#include "core/layout/LayoutPart.h"
#include "core/layout/LayoutQuote.h"
#include "core/layout/LayoutScrollbarPart.h"
#include "core/layout/ViewFragmentationContext.h"
#include "core/layout/compositing/PaintLayerCompositor.h"
#include "core/page/Page.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/ViewPainter.h"
#include "core/svg/SVGDocumentExtensions.h"
#include "platform/TraceEvent.h"
#include "platform/TracedValue.h"
#include "platform/geometry/FloatQuad.h"
#include "platform/geometry/TransformState.h"
#include "platform/graphics/paint/PaintController.h"
#include "public/platform/Platform.h"
#include <inttypes.h>

namespace blink {

namespace {

class HitTestLatencyRecorder {
public:
    HitTestLatencyRecorder(bool allowsChildFrameContent)
        : m_start(WTF::monotonicallyIncreasingTime())
        , m_allowsChildFrameContent(allowsChildFrameContent)
    {
    }

    ~HitTestLatencyRecorder()
    {
        int duration = static_cast<int>((WTF::monotonicallyIncreasingTime() - m_start) * 1000000);
        Platform::current()->histogramCustomCounts(m_allowsChildFrameContent ? "Event.Latency.HitTestRecursive" : "Event.Latency.HitTest", duration, 0, 10000000, 100);
    }

private:
    double m_start;
    bool m_allowsChildFrameContent;
};

} // namespace

LayoutView::LayoutView(Document* document)
    : LayoutBlockFlow(document)
    , m_frameView(document->view())
    , m_selectionStart(nullptr)
    , m_selectionEnd(nullptr)
    , m_selectionStartPos(-1)
    , m_selectionEndPos(-1)
    , m_pageLogicalHeight(0)
    , m_pageLogicalHeightChanged(false)
    , m_layoutState(nullptr)
    , m_layoutQuoteHead(nullptr)
    , m_layoutCounterCount(0)
    , m_hitTestCount(0)
    , m_hitTestCacheHits(0)
    , m_hitTestCache(HitTestCache::create())
{
    // init LayoutObject attributes
    setInline(false);

    m_minPreferredLogicalWidth = 0;
    m_maxPreferredLogicalWidth = 0;

    setPreferredLogicalWidthsDirty(MarkOnlyThis);

    setPositionState(AbsolutePosition); // to 0,0 :)
}

LayoutView::~LayoutView()
{
}

bool LayoutView::hitTest(HitTestResult& result)
{
    // We have to recursively update layout/style here because otherwise, when the hit test recurses
    // into a child document, it could trigger a layout on the parent document, which can destroy PaintLayer
    // that are higher up in the call stack, leading to crashes.
    // Note that Document::updateLayout calls its parent's updateLayout.
    DocumentLifecycle::PreventThrottlingScope preventThrottling(document().lifecycle());
    frameView()->updateLifecycleToCompositingCleanPlusScrolling();
    HitTestLatencyRecorder hitTestLatencyRecorder(result.hitTestRequest().allowsChildFrameContent());
    return hitTestNoLifecycleUpdate(result);
}

bool LayoutView::hitTestNoLifecycleUpdate(HitTestResult& result)
{
    TRACE_EVENT_BEGIN0("blink,devtools.timeline", "HitTest");
    m_hitTestCount++;

    ASSERT(!result.hitTestLocation().isRectBasedTest() || result.hitTestRequest().listBased());

    commitPendingSelection();

    uint64_t domTreeVersion = document().domTreeVersion();
    HitTestResult cacheResult = result;
    bool hitLayer = false;
    if (m_hitTestCache->lookupCachedResult(cacheResult, domTreeVersion)) {
        m_hitTestCacheHits++;
        hitLayer = true;
        result = cacheResult;
    } else {
        hitLayer = layer()->hitTest(result);

        // FrameView scrollbars are not the same as Layer scrollbars tested by Layer::hitTestOverflowControls,
        // so we need to test FrameView scrollbars separately here. Note that it's important we do this after
        // the hit test above, because that may overwrite the entire HitTestResult when it finds a hit.
        IntPoint framePoint = frameView()->contentsToFrame(result.hitTestLocation().roundedPoint());
        if (Scrollbar* frameScrollbar = frameView()->scrollbarAtFramePoint(framePoint))
            result.setScrollbar(frameScrollbar);

        if (hitLayer)
            m_hitTestCache->addCachedResult(result, domTreeVersion);
    }

    TRACE_EVENT_END1("blink,devtools.timeline", "HitTest", "endData", InspectorHitTestEvent::endData(result.hitTestRequest(), result.hitTestLocation(), result));
    return hitLayer;
}

void LayoutView::clearHitTestCache()
{
    m_hitTestCache->clear();
    if (LayoutPart* frameLayoutObject = frame()->ownerLayoutObject())
        frameLayoutObject->view()->clearHitTestCache();
}

void LayoutView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit, LogicalExtentComputedValues& computedValues) const
{
    computedValues.m_extent = viewLogicalHeightForBoxSizing();
}

void LayoutView::updateLogicalWidth()
{
    setLogicalWidth(viewLogicalWidthForBoxSizing());
}

bool LayoutView::isChildAllowed(LayoutObject* child, const ComputedStyle&) const
{
    return child->isBox();
}

void LayoutView::layoutContent()
{
    ASSERT(needsLayout());

    LayoutBlockFlow::layout();

#if ENABLE(ASSERT)
    checkLayoutState();
#endif
}

#if ENABLE(ASSERT)
void LayoutView::checkLayoutState()
{
    ASSERT(!m_layoutState->next());
}
#endif

bool LayoutView::shouldDoFullPaintInvalidationForNextLayout() const
{
    // It's hard to predict here which of full paint invalidation or per-descendant paint invalidation costs less.
    // For vertical writing mode or width change it's more likely that per-descendant paint invalidation
    // eventually turns out to be full paint invalidation but with the cost to handle more layout states
    // and discrete paint invalidation rects, so marking full paint invalidation here is more likely to cost less.
    // Otherwise, per-descendant paint invalidation is more likely to avoid unnecessary full paint invalidation.

    if (shouldUsePrintingLayout())
        return true;

    if (!style()->isHorizontalWritingMode())
        return true;

    // The width/height checks below assume horizontal writing mode.
    ASSERT(style()->isHorizontalWritingMode());

    if (size().width() != viewLogicalWidthForBoxSizing())
        return true;

    if (size().height() != viewLogicalHeightForBoxSizing()) {
        // When background-attachment is 'fixed', we treat the viewport (instead of the 'root'
        // i.e. html or body) as the background positioning area, and we should full paint invalidation
        // viewport resize if the background image is not composited and needs full paint invalidation on
        // background positioning area resize.
        if (!m_compositor || !m_compositor->needsFixedRootBackgroundLayer(layer())) {
            if (style()->hasFixedBackgroundImage()
                && mustInvalidateFillLayersPaintOnHeightChange(style()->backgroundLayers()))
                return true;
        }
    }

    return false;
}

bool LayoutView::doingFullPaintInvalidation() const
{
    return m_frameView->needsFullPaintInvalidation();
}

void LayoutView::layout()
{
    if (!document().paginated())
        setPageLogicalHeight(0);

    if (shouldUsePrintingLayout()) {
        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
        if (!m_fragmentationContext)
            m_fragmentationContext = adoptPtr(new ViewFragmentationContext(*this));
    } else if (m_fragmentationContext) {
        m_fragmentationContext.clear();
    }

    SubtreeLayoutScope layoutScope(*this);

    LayoutRect oldLayoutOverflowRect = layoutOverflowRect();

    // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
    bool relayoutChildren = !shouldUsePrintingLayout() && (!m_frameView
        || logicalWidth() != viewLogicalWidthForBoxSizing()
        || logicalHeight() != viewLogicalHeightForBoxSizing());
    if (relayoutChildren) {
        layoutScope.setChildNeedsLayout(this);
        for (LayoutObject* child = firstChild(); child; child = child->nextSibling()) {
            if (child->isSVGRoot())
                continue;

            if ((child->isBox() && toLayoutBox(child)->hasRelativeLogicalHeight())
                || child->style()->logicalHeight().hasPercent()
                || child->style()->logicalMinHeight().hasPercent()
                || child->style()->logicalMaxHeight().hasPercent())
                layoutScope.setChildNeedsLayout(child);
        }

        if (document().svgExtensions())
            document().accessSVGExtensions().invalidateSVGRootsWithRelativeLengthDescendents(&layoutScope);
    }

    ASSERT(!m_layoutState);
    if (!needsLayout())
        return;

    LayoutState rootLayoutState(pageLogicalHeight(), pageLogicalHeightChanged(), *this);

    m_pageLogicalHeightChanged = false;

    layoutContent();

    if (layoutOverflowRect() != oldLayoutOverflowRect) {
        // The document element paints the viewport background, so we need to invalidate it when
        // layout overflow changes.
        // FIXME: Improve viewport background styling/invalidation/painting. crbug.com/475115
        if (Element* documentElement = document().documentElement()) {
            if (LayoutObject* rootObject = documentElement->layoutObject())
                rootObject->setShouldDoFullPaintInvalidation();
        }
    }

#if ENABLE(ASSERT)
    checkLayoutState();
#endif
    clearNeedsLayout();
}

LayoutRect LayoutView::visualOverflowRect() const
{
    // In root layer scrolling mode, the LayoutView performs overflow clipping
    // like a regular scrollable div.
    if (document().settings() && document().settings()->rootLayerScrolls())
        return LayoutBlockFlow::visualOverflowRect();

    // Ditto when not in compositing mode.
    if (!usesCompositing())
        return LayoutBlockFlow::visualOverflowRect();

    // In normal compositing mode, LayoutView doesn't actually apply clipping
    // on its descendants. Instead their visual overflow is propagated to
    // compositor()->m_rootContentLayer for accelerated scrolling.
    return LayoutRect(documentRect());
}

void LayoutView::mapLocalToAncestor(const LayoutBoxModelObject* ancestor, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const
{
    ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == static_cast<bool>(mode & IsFixed));

    if (!ancestor && mode & UseTransforms && shouldUseTransformFromContainer(0)) {
        TransformationMatrix t;
        getTransformFromContainer(0, LayoutSize(), t);
        transformState.applyTransform(t);
    }

    if ((mode & IsFixed) && m_frameView) {
        transformState.move(toIntSize(m_frameView->scrollPosition()));
        if (hasOverflowClip())
            transformState.move(scrolledContentOffset());
        // IsFixed flag is only applicable within this LayoutView.
        mode &= ~IsFixed;
    }

    if (ancestor == this)
        return;

    if (mode & TraverseDocumentBoundaries) {
        if (LayoutPart* parentDocLayoutObject = frame()->ownerLayoutObject()) {
            transformState.move(-frame()->view()->scrollOffset());
            transformState.move(parentDocLayoutObject->contentBoxOffset());

            parentDocLayoutObject->mapLocalToAncestor(ancestor, transformState, mode, wasFixed, paintInvalidationState);
        }
    }
}

const LayoutObject* LayoutView::pushMappingToContainer(const LayoutBoxModelObject* ancestorToStopAt, LayoutGeometryMap& geometryMap) const
{
    LayoutSize offsetForFixedPosition;
    LayoutSize offset;
    LayoutObject* container = nullptr;

    if (m_frameView) {
        offsetForFixedPosition = LayoutSize(toIntSize(m_frameView->scrollPosition()));
        if (hasOverflowClip())
            offsetForFixedPosition = LayoutSize(scrolledContentOffset());
    }

    if (geometryMap.mapCoordinatesFlags() & TraverseDocumentBoundaries) {
        if (LayoutPart* parentDocLayoutObject = frame()->ownerLayoutObject()) {
            offset = -LayoutSize(m_frameView->scrollOffset());
            offset += parentDocLayoutObject->contentBoxOffset();
            container = parentDocLayoutObject;
        }
    }

    // If a container was specified, and was not 0 or the LayoutView, then we
    // should have found it by now unless we're traversing to a parent document.
    ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this || container);

    if ((!ancestorToStopAt || container) && shouldUseTransformFromContainer(container)) {
        TransformationMatrix t;
        getTransformFromContainer(container, LayoutSize(), t);
        geometryMap.push(this, t, false, false, false, true, offsetForFixedPosition);
    } else {
        geometryMap.push(this, offset, false, false, false, false, offsetForFixedPosition);
    }

    return container;
}

void LayoutView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
{
    if (mode & IsFixed && m_frameView)
        transformState.move(toIntSize(m_frameView->scrollPosition()));

    if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
        TransformationMatrix t;
        getTransformFromContainer(0, LayoutSize(), t);
        transformState.applyTransform(t);
    }

    if (mode & TraverseDocumentBoundaries) {
        if (LayoutPart* parentDocLayoutObject = frame()->ownerLayoutObject()) {
            parentDocLayoutObject->mapAbsoluteToLocalPoint(mode, transformState);
            transformState.move(parentDocLayoutObject->contentBoxOffset());
            transformState.move(-frame()->view()->scrollOffset());
        }
    }
}

void LayoutView::computeSelfHitTestRects(Vector<LayoutRect>& rects, const LayoutPoint&) const
{
    // Record the entire size of the contents of the frame. Note that we don't just
    // use the viewport size (containing block) here because we want to ensure this includes
    // all children (so we can avoid walking them explicitly).
    rects.append(LayoutRect(LayoutPoint::zero(), LayoutSize(frameView()->contentsSize())));
}

void LayoutView::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const
{
    ViewPainter(*this).paint(paintInfo, paintOffset);
}

void LayoutView::paintBoxDecorationBackground(const PaintInfo& paintInfo, const LayoutPoint&) const
{
    ViewPainter(*this).paintBoxDecorationBackground(paintInfo);
}

void LayoutView::invalidateTreeIfNeeded(PaintInvalidationState& paintInvalidationState)
{
    ASSERT(!needsLayout());

    // We specifically need to issue paint invalidations for the viewRect since other layoutObjects
    // short-circuit on full-paint invalidation.
    LayoutRect dirtyRect = viewRect();
    if (doingFullPaintInvalidation() && !dirtyRect.isEmpty()) {
        const LayoutBoxModelObject& paintInvalidationContainer = paintInvalidationState.paintInvalidationContainer();
        PaintLayer::mapRectToPaintInvalidationBacking(this, &paintInvalidationContainer, dirtyRect, &paintInvalidationState);
        invalidatePaintUsingContainer(paintInvalidationContainer, dirtyRect, PaintInvalidationFull);
        invalidateDisplayItemClientsWithPaintInvalidationState(paintInvalidationContainer, paintInvalidationState, PaintInvalidationFull);
    }
    LayoutBlock::invalidateTreeIfNeeded(paintInvalidationState);
}

static void setShouldDoFullPaintInvalidationForViewAndAllDescendantsInternal(LayoutObject* object)
{
    object->setShouldDoFullPaintInvalidation();
    for (LayoutObject* child = object->slowFirstChild(); child; child = child->nextSibling()) {
        setShouldDoFullPaintInvalidationForViewAndAllDescendantsInternal(child);
    }
}

void LayoutView::setShouldDoFullPaintInvalidationForViewAndAllDescendants()
{
    setShouldDoFullPaintInvalidationForViewAndAllDescendantsInternal(this);
}

void LayoutView::invalidatePaintForViewAndCompositedLayers()
{
    setShouldDoFullPaintInvalidation();

    // The only way we know how to hit these ASSERTS below this point is via the Chromium OS login screen.
    DisableCompositingQueryAsserts disabler;

    if (compositor()->inCompositingMode())
        compositor()->fullyInvalidatePaint();
}

void LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, const PaintInvalidationState* invalidationState) const
{
    mapToVisibleRectInAncestorSpace(ancestor, rect, IsNotFixedPosition, invalidationState);
}

void LayoutView::mapToVisibleRectInAncestorSpace(const LayoutBoxModelObject* ancestor, LayoutRect& rect, ViewportConstrainedPosition viewportConstraint, const PaintInvalidationState* state) const
{
    if (document().printing())
        return;

    if (style()->isFlippedBlocksWritingMode()) {
        // We have to flip by hand since the view's logical height has not been determined.  We
        // can use the viewport width and height.
        if (style()->isHorizontalWritingMode())
            rect.setY(viewHeight() - rect.maxY());
        else
            rect.setX(viewWidth() - rect.maxX());
    }

    adjustViewportConstrainedOffset(rect, viewportConstraint);

    // Apply our transform if we have one (because of full page zooming).
    if (!ancestor && layer() && layer()->transform())
        rect = layer()->transform()->mapRect(rect);

    ASSERT(ancestor);
    if (ancestor == this)
        return;

    Element* owner = document().ownerElement();
    if (!owner)
        return;

    if (LayoutBox* obj = owner->layoutBox()) {
        if (!state || !state->viewClippingAndScrollOffsetDisabled()) {
            // Intersect the viewport with the paint invalidation rect.
            LayoutRect viewRectangle = viewRect();
            rect.intersect(viewRectangle);

            // Adjust for scroll offset of the view.
            rect.moveBy(-viewRectangle.location());
        }

        // Adjust for frame border.
        rect.move(obj->contentBoxOffset());
        obj->mapToVisibleRectInAncestorSpace(ancestor, rect, 0);
    }
}

void LayoutView::adjustViewportConstrainedOffset(LayoutRect& rect, ViewportConstrainedPosition viewportConstraint) const
{
    if (viewportConstraint != IsFixedPosition)
        return;

    if (m_frameView) {
        rect.move(toIntSize(m_frameView->scrollPosition()));
        if (hasOverflowClip())
            rect.move(scrolledContentOffset());

        // FIXME: Paint invalidation should happen after scroll updates, so there should be no pending scroll delta.
        // However, we still have paint invalidation during layout, so we can't ASSERT for now. crbug.com/434950.
        // ASSERT(m_frameView->pendingScrollDelta().isZero());
        // If we have a pending scroll, invalidate the previous scroll position.
        if (!m_frameView->pendingScrollDelta().isZero())
            rect.move(-LayoutSize(m_frameView->pendingScrollDelta()));
    }
}

void LayoutView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
{
    rects.append(pixelSnappedIntRect(accumulatedOffset, LayoutSize(layer()->size())));
}

void LayoutView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
{
    if (wasFixed)
        *wasFixed = false;
    quads.append(FloatRect(FloatPoint(), FloatSize(layer()->size())));
}

static LayoutObject* layoutObjectAfterPosition(LayoutObject* object, unsigned offset)
{
    if (!object)
        return nullptr;

    LayoutObject* child = object->childAt(offset);
    return child ? child : object->nextInPreOrderAfterChildren();
}

static LayoutRect selectionRectForLayoutObject(const LayoutObject* object)
{
    if (!object->isRooted())
        return LayoutRect();

    if (!object->canUpdateSelectionOnRootLineBoxes())
        return LayoutRect();

    return object->selectionRectInViewCoordinates();
}

IntRect LayoutView::selectionBounds()
{
    // Now create a single bounding box rect that encloses the whole selection.
    LayoutRect selRect;

    typedef HashSet<const LayoutBlock*> VisitedContainingBlockSet;
    VisitedContainingBlockSet visitedContainingBlocks;

    commitPendingSelection();
    LayoutObject* os = m_selectionStart;
    LayoutObject* stop = layoutObjectAfterPosition(m_selectionEnd, m_selectionEndPos);
    while (os && os != stop) {
        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
            // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
            selRect.unite(selectionRectForLayoutObject(os));
            const LayoutBlock* cb = os->containingBlock();
            while (cb && !cb->isLayoutView()) {
                selRect.unite(selectionRectForLayoutObject(cb));
                VisitedContainingBlockSet::AddResult addResult = visitedContainingBlocks.add(cb);
                if (!addResult.isNewEntry)
                    break;
                cb = cb->containingBlock();
            }
        }

        os = os->nextInPreOrder();
    }

    return pixelSnappedIntRect(selRect);
}

void LayoutView::invalidatePaintForSelection()
{
    HashSet<LayoutBlock*> processedBlocks;

    LayoutObject* end = layoutObjectAfterPosition(m_selectionEnd, m_selectionEndPos);
    for (LayoutObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
        if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
            continue;
        if (o->selectionState() == SelectionNone)
            continue;

        o->setShouldInvalidateSelection();

        // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
        for (LayoutBlock* block = o->containingBlock(); block && !block->isLayoutView(); block = block->containingBlock()) {
            if (!processedBlocks.add(block).isNewEntry)
                break;
            block->setShouldInvalidateSelection();
        }
    }
}

// When exploring the LayoutTree looking for the nodes involved in the Selection, sometimes it's
// required to change the traversing direction because the "start" position is below the "end" one.
static inline LayoutObject* getNextOrPrevLayoutObjectBasedOnDirection(const LayoutObject* o, const LayoutObject* stop, bool& continueExploring, bool& exploringBackwards)
{
    LayoutObject* next;
    if (exploringBackwards) {
        next = o->previousInPreOrder();
        continueExploring = next && !(next)->isLayoutView();
    } else {
        next = o->nextInPreOrder();
        continueExploring = next && next != stop;
        exploringBackwards = !next && (next != stop);
        if (exploringBackwards) {
            next = stop->previousInPreOrder();
            continueExploring = next && !next->isLayoutView();
        }
    }

    return next;
}

void LayoutView::setSelection(LayoutObject* start, int startPos, LayoutObject* end, int endPos, SelectionPaintInvalidationMode blockPaintInvalidationMode)
{
    // This code makes no assumptions as to if the layout tree is up to date or not
    // and will not try to update it. Currently clearSelection calls this
    // (intentionally) without updating the layout tree as it doesn't care.
    // Other callers may want to force recalc style before calling this.

    // Make sure both our start and end objects are defined.
    // Check www.msnbc.com and try clicking around to find the case where this happened.
    if ((start && !end) || (end && !start))
        return;

    // Just return if the selection hasn't changed.
    if (m_selectionStart == start && m_selectionStartPos == startPos
        && m_selectionEnd == end && m_selectionEndPos == endPos)
        return;

    // Record the old selected objects.  These will be used later
    // when we compare against the new selected objects.
    int oldStartPos = m_selectionStartPos;
    int oldEndPos = m_selectionEndPos;

    // Objects each have a single selection rect to examine.
    typedef HashMap<LayoutObject*, SelectionState> SelectedObjectMap;
    SelectedObjectMap oldSelectedObjects;
    // FIXME: |newSelectedObjects| doesn't really need to store the SelectionState, it's just more convenient
    // to have it use the same data structure as |oldSelectedObjects|.
    SelectedObjectMap newSelectedObjects;

    // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
    // In order to get the paint invalidation rect right, we have to examine left, middle, and right rects individually, since otherwise
    // the union of those rects might remain the same even when changes have occurred.
    typedef HashMap<LayoutBlock*, SelectionState> SelectedBlockMap;
    SelectedBlockMap oldSelectedBlocks;
    // FIXME: |newSelectedBlocks| doesn't really need to store the SelectionState, it's just more convenient
    // to have it use the same data structure as |oldSelectedBlocks|.
    SelectedBlockMap newSelectedBlocks;

    LayoutObject* os = m_selectionStart;
    LayoutObject* stop = layoutObjectAfterPosition(m_selectionEnd, m_selectionEndPos);
    bool exploringBackwards = false;
    bool continueExploring = os && (os != stop);
    while (continueExploring) {
        if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) {
            // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
            oldSelectedObjects.set(os, os->selectionState());
            if (blockPaintInvalidationMode == PaintInvalidationNewXOROld) {
                LayoutBlock* cb = os->containingBlock();
                while (cb && !cb->isLayoutView()) {
                    SelectedBlockMap::AddResult result = oldSelectedBlocks.add(cb, cb->selectionState());
                    if (!result.isNewEntry)
                        break;
                    cb = cb->containingBlock();
                }
            }
        }

        os = getNextOrPrevLayoutObjectBasedOnDirection(os, stop, continueExploring, exploringBackwards);
    }

    // Now clear the selection.
    SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
        i->key->setSelectionStateIfNeeded(SelectionNone);

    // set selection start and end
    m_selectionStart = start;
    m_selectionStartPos = startPos;
    m_selectionEnd = end;
    m_selectionEndPos = endPos;

    // Update the selection status of all objects between m_selectionStart and m_selectionEnd
    if (start && start == end) {
        start->setSelectionStateIfNeeded(SelectionBoth);
    } else {
        if (start)
            start->setSelectionStateIfNeeded(SelectionStart);
        if (end)
            end->setSelectionStateIfNeeded(SelectionEnd);
    }

    LayoutObject* o = start;
    stop = layoutObjectAfterPosition(end, endPos);

    while (o && o != stop) {
        if (o != start && o != end && o->canBeSelectionLeaf())
            o->setSelectionStateIfNeeded(SelectionInside);
        o = o->nextInPreOrder();
    }

    layer()->clearBlockSelectionGapsBounds();

    // Now that the selection state has been updated for the new objects, walk them again and
    // put them in the new objects list.
    o = start;
    exploringBackwards = false;
    continueExploring = o && (o != stop);
    while (continueExploring) {
        if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) {
            newSelectedObjects.set(o, o->selectionState());
            LayoutBlock* cb = o->containingBlock();
            while (cb && !cb->isLayoutView()) {
                SelectedBlockMap::AddResult result = newSelectedBlocks.add(cb, cb->selectionState());
                if (!result.isNewEntry)
                    break;
                cb = cb->containingBlock();
            }
        }

        o = getNextOrPrevLayoutObjectBasedOnDirection(o, stop, continueExploring, exploringBackwards);
    }

    if (!m_frameView)
        return;

    // Have any of the old selected objects changed compared to the new selection?
    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
        LayoutObject* obj = i->key;
        SelectionState newSelectionState = obj->selectionState();
        SelectionState oldSelectionState = i->value;
        if (newSelectionState != oldSelectionState
            || (m_selectionStart == obj && oldStartPos != m_selectionStartPos)
            || (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
            obj->setShouldInvalidateSelection();
            newSelectedObjects.remove(obj);
        }
    }

    // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
    SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
    for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
        i->key->setShouldInvalidateSelection();

    // Have any of the old blocks changed?
    SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
    for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
        LayoutBlock* block = i->key;
        SelectionState newSelectionState = block->selectionState();
        SelectionState oldSelectionState = i->value;
        if (newSelectionState != oldSelectionState) {
            block->setShouldInvalidateSelection();
            newSelectedBlocks.remove(block);
        }
    }

    // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
    SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
    for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
        i->key->setShouldInvalidateSelection();
}

void LayoutView::clearSelection()
{
    // For querying Layer::compositingState()
    // This is correct, since destroying layout objects needs to cause eager paint invalidations.
    DisableCompositingQueryAsserts disabler;

    layer()->invalidatePaintForBlockSelectionGaps();
    setSelection(0, -1, 0, -1, PaintInvalidationNewMinusOld);
}

bool LayoutView::hasPendingSelection() const
{
    return m_frameView->frame().selection().isAppearanceDirty();
}

void LayoutView::commitPendingSelection()
{
    m_frameView->frame().selection().commitAppearanceIfNeeded(*this);
}

LayoutObject* LayoutView::selectionStart()
{
    commitPendingSelection();
    return m_selectionStart;
}

LayoutObject* LayoutView::selectionEnd()
{
    commitPendingSelection();
    return m_selectionEnd;
}

void LayoutView::selectionStartEnd(int& startPos, int& endPos)
{
    commitPendingSelection();
    startPos = m_selectionStartPos;
    endPos = m_selectionEndPos;
}

bool LayoutView::shouldUsePrintingLayout() const
{
    if (!document().printing() || !m_frameView)
        return false;
    return m_frameView->frame().shouldUsePrintingLayout();
}

LayoutRect LayoutView::viewRect() const
{
    if (shouldUsePrintingLayout())
        return LayoutRect(LayoutPoint(), size());
    if (m_frameView)
        return LayoutRect(m_frameView->visibleContentRect());
    return LayoutRect();
}

LayoutRect LayoutView::overflowClipRect(const LayoutPoint& location, OverlayScrollbarSizeRelevancy relevancy) const
{
    LayoutRect rect = viewRect();
    if (rect.isEmpty())
        return LayoutBox::overflowClipRect(location, relevancy);

    rect.setLocation(location);
    if (hasOverflowClip())
        excludeScrollbars(rect, relevancy);

    return rect;
}

IntRect LayoutView::documentRect() const
{
    LayoutRect overflowRect(layoutOverflowRect());
    flipForWritingMode(overflowRect);
    return pixelSnappedIntRect(overflowRect);
}

bool LayoutView::rootBackgroundIsEntirelyFixed() const
{
    return style()->hasEntirelyFixedBackground();
}

LayoutRect LayoutView::backgroundRect(LayoutBox* backgroundLayoutObject) const
{
    return LayoutRect(documentRect());
}

IntSize LayoutView::layoutSize(IncludeScrollbarsInRect scrollbarInclusion) const
{
    if (shouldUsePrintingLayout())
        return IntSize(size().width(), pageLogicalHeight());

    if (!m_frameView)
        return IntSize();

    IntSize result = m_frameView->layoutSize(IncludeScrollbars);
    if (scrollbarInclusion == ExcludeScrollbars)
        result = m_frameView->layoutViewportScrollableArea()->excludeScrollbars(result);
    return result;
}

int LayoutView::viewLogicalWidth(IncludeScrollbarsInRect scrollbarInclusion) const
{
    return style()->isHorizontalWritingMode() ? viewWidth(scrollbarInclusion) : viewHeight(scrollbarInclusion);
}

int LayoutView::viewLogicalHeight(IncludeScrollbarsInRect scrollbarInclusion) const
{
    return style()->isHorizontalWritingMode() ? viewHeight(scrollbarInclusion) : viewWidth(scrollbarInclusion);
}

int LayoutView::viewLogicalWidthForBoxSizing() const
{
    return viewLogicalWidth(document().settings() && document().settings()->rootLayerScrolls() ? IncludeScrollbars : ExcludeScrollbars);
}

int LayoutView::viewLogicalHeightForBoxSizing() const
{
    return viewLogicalHeight(document().settings() && document().settings()->rootLayerScrolls() ? IncludeScrollbars : ExcludeScrollbars);
}

LayoutUnit LayoutView::viewLogicalHeightForPercentages() const
{
    if (shouldUsePrintingLayout())
        return pageLogicalHeight();
    return viewLogicalHeight();
}

float LayoutView::zoomFactor() const
{
    return m_frameView->frame().pageZoomFactor();
}

void LayoutView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
{
    if (result.innerNode())
        return;

    Node* node = document().documentElement();
    if (node) {
        LayoutPoint adjustedPoint = point;
        offsetForContents(adjustedPoint);
        result.setNodeAndPosition(node, adjustedPoint);
    }
}

bool LayoutView::usesCompositing() const
{
    return m_compositor && m_compositor->staleInCompositingMode();
}

PaintLayerCompositor* LayoutView::compositor()
{
    if (!m_compositor)
        m_compositor = adoptPtr(new PaintLayerCompositor(*this));

    return m_compositor.get();
}

void LayoutView::setIsInWindow(bool isInWindow)
{
    if (m_compositor)
        m_compositor->setIsInWindow(isInWindow);
}

IntervalArena* LayoutView::intervalArena()
{
    if (!m_intervalArena)
        m_intervalArena = IntervalArena::create();
    return m_intervalArena.get();
}

bool LayoutView::backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const
{
    // FIXME: Remove this main frame check. Same concept applies to subframes too.
    if (!frame()->isMainFrame())
        return false;

    return m_frameView->hasOpaqueBackground();
}

FloatSize LayoutView::viewportSizeForViewportUnits() const
{
    return frameView() ? frameView()->viewportSizeForViewportUnits() : FloatSize();
}

void LayoutView::willBeDestroyed()
{
    // TODO(wangxianzhu): This is a workaround of crbug.com/570706.
    // Should find and fix the root cause.
    if (PaintLayer* layer = this->layer())
        layer->setNeedsRepaint();
    LayoutBlockFlow::willBeDestroyed();
    m_compositor.clear();
}

void LayoutView::registerMediaForPositionChangeNotification(LayoutMedia& media)
{
    if (!m_mediaForPositionNotification.contains(&media))
        m_mediaForPositionNotification.append(&media);
}

void LayoutView::unregisterMediaForPositionChangeNotification(LayoutMedia& media)
{
    size_t at = m_mediaForPositionNotification.find(&media);
    if (at != kNotFound)
        m_mediaForPositionNotification.remove(at);
}

void LayoutView::sendMediaPositionChangeNotifications(const IntRect& visibleRect)
{
    for (auto& media : m_mediaForPositionNotification) {
        media->notifyPositionMayHaveChanged(visibleRect);
    }
}

} // namespace blink
