/*
 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials
 *    provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "config.h"
#include "RenderFragmentContainer.h"

#include "GraphicsContext.h"
#include "HitTestResult.h"
#include "IntRect.h"
#include "LayoutRepainter.h"
#include "Range.h"
#include "RenderBoxFragmentInfo.h"
#include "RenderFragmentedFlow.h"
#include "RenderInline.h"
#include "RenderIterator.h"
#include "RenderLayer.h"
#include "RenderView.h"
#include "StyleResolver.h"
#include <wtf/HexNumber.h>
#include <wtf/IsoMallocInlines.h>

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(RenderFragmentContainer);

RenderFragmentContainer::RenderFragmentContainer(Element& element, RenderStyle&& style, RenderFragmentedFlow* fragmentedFlow)
    : RenderBlockFlow(element, WTFMove(style))
    , m_fragmentedFlow(fragmentedFlow)
{
}

RenderFragmentContainer::RenderFragmentContainer(Document& document, RenderStyle&& style, RenderFragmentedFlow* fragmentedFlow)
    : RenderBlockFlow(document, WTFMove(style))
    , m_fragmentedFlow(fragmentedFlow)
{
}

LayoutPoint RenderFragmentContainer::mapFragmentPointIntoFragmentedFlowCoordinates(const LayoutPoint& point)
{
    // Assuming the point is relative to the fragment block, 3 cases will be considered:
    // a) top margin, padding or border.
    // b) bottom margin, padding or border.
    // c) non-content fragment area.

    LayoutUnit pointLogicalTop(isHorizontalWritingMode() ? point.y() : point.x());
    LayoutUnit pointLogicalLeft(isHorizontalWritingMode() ? point.x() : point.y());
    LayoutUnit fragmentedFlowLogicalTop(isHorizontalWritingMode() ? m_fragmentedFlowPortionRect.y() : m_fragmentedFlowPortionRect.x());
    LayoutUnit fragmentedFlowLogicalLeft(isHorizontalWritingMode() ? m_fragmentedFlowPortionRect.x() : m_fragmentedFlowPortionRect.y());
    LayoutUnit fragmentedFlowPortionTopBound(isHorizontalWritingMode() ? m_fragmentedFlowPortionRect.height() : m_fragmentedFlowPortionRect.width());
    LayoutUnit fragmentedFlowPortionLeftBound(isHorizontalWritingMode() ? m_fragmentedFlowPortionRect.width() : m_fragmentedFlowPortionRect.height());
    LayoutUnit fragmentedFlowPortionTopMax(isHorizontalWritingMode() ? m_fragmentedFlowPortionRect.maxY() : m_fragmentedFlowPortionRect.maxX());
    LayoutUnit fragmentedFlowPortionLeftMax(isHorizontalWritingMode() ? m_fragmentedFlowPortionRect.maxX() : m_fragmentedFlowPortionRect.maxY());
    LayoutUnit effectiveFixedPointDenominator;
    effectiveFixedPointDenominator.setRawValue(1);

    if (pointLogicalTop < 0) {
        LayoutPoint pointInThread(0_lu, fragmentedFlowLogicalTop);
        return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
    }

    if (pointLogicalTop >= fragmentedFlowPortionTopBound) {
        LayoutPoint pointInThread(fragmentedFlowPortionLeftBound, fragmentedFlowPortionTopMax - effectiveFixedPointDenominator);
        return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
    }

    if (pointLogicalLeft < 0) {
        LayoutPoint pointInThread(fragmentedFlowLogicalLeft, pointLogicalTop + fragmentedFlowLogicalTop);
        return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
    }
    if (pointLogicalLeft >= fragmentedFlowPortionLeftBound) {
        LayoutPoint pointInThread(fragmentedFlowPortionLeftMax - effectiveFixedPointDenominator, pointLogicalTop + fragmentedFlowLogicalTop);
        return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
    }
    LayoutPoint pointInThread(pointLogicalLeft + fragmentedFlowLogicalLeft, pointLogicalTop + fragmentedFlowLogicalTop);
    return isHorizontalWritingMode() ? pointInThread : pointInThread.transposedPoint();
}

VisiblePosition RenderFragmentContainer::positionForPoint(const LayoutPoint& point, const RenderFragmentContainer* fragment)
{
    if (!isValid() || !m_fragmentedFlow->firstChild()) // checking for empty fragment blocks.
        return RenderBlock::positionForPoint(point, fragment);

    return m_fragmentedFlow->positionForPoint(mapFragmentPointIntoFragmentedFlowCoordinates(point), this);
}

LayoutUnit RenderFragmentContainer::pageLogicalWidth() const
{
    ASSERT(isValid());
    return m_fragmentedFlow->isHorizontalWritingMode() ? contentWidth() : contentHeight();
}

LayoutUnit RenderFragmentContainer::pageLogicalHeight() const
{
    ASSERT(isValid());
    return m_fragmentedFlow->isHorizontalWritingMode() ? contentHeight() : contentWidth();
}

LayoutUnit RenderFragmentContainer::logicalHeightOfAllFragmentedFlowContent() const
{
    return pageLogicalHeight();
}

LayoutRect RenderFragmentContainer::fragmentedFlowPortionOverflowRect()
{
    return overflowRectForFragmentedFlowPortion(fragmentedFlowPortionRect(), isFirstFragment(), isLastFragment(), VisualOverflow);
}

LayoutPoint RenderFragmentContainer::fragmentedFlowPortionLocation() const
{
    LayoutPoint portionLocation;
    LayoutRect portionRect = fragmentedFlowPortionRect();

    if (fragmentedFlow()->style().isFlippedBlocksWritingMode()) {
        LayoutRect flippedFragmentedFlowPortionRect(portionRect);
        fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionRect);
        portionLocation = flippedFragmentedFlowPortionRect.location();
    } else
        portionLocation = portionRect.location();

    return portionLocation;
}

LayoutRect RenderFragmentContainer::overflowRectForFragmentedFlowPortion(const LayoutRect& fragmentedFlowPortionRect, bool isFirstPortion, bool isLastPortion, OverflowType overflowType)
{
    ASSERT(isValid());
    if (shouldClipFragmentedFlowContent())
        return fragmentedFlowPortionRect;

    LayoutRect fragmentedFlowOverflow = overflowType == VisualOverflow ? visualOverflowRectForBox(*m_fragmentedFlow) : layoutOverflowRectForBox(m_fragmentedFlow);
    LayoutRect clipRect;
    if (m_fragmentedFlow->isHorizontalWritingMode()) {
        LayoutUnit minY = isFirstPortion ? fragmentedFlowOverflow.y() : fragmentedFlowPortionRect.y();
        LayoutUnit maxY = isLastPortion ? std::max(fragmentedFlowPortionRect.maxY(), fragmentedFlowOverflow.maxY()) : fragmentedFlowPortionRect.maxY();
        bool clipX = effectiveOverflowX() != Overflow::Visible;
        LayoutUnit minX = clipX ? fragmentedFlowPortionRect.x() : std::min(fragmentedFlowPortionRect.x(), fragmentedFlowOverflow.x());
        LayoutUnit maxX = clipX ? fragmentedFlowPortionRect.maxX() : std::max(fragmentedFlowPortionRect.maxX(), fragmentedFlowOverflow.maxX());
        clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
    } else {
        LayoutUnit minX = isFirstPortion ? fragmentedFlowOverflow.x() : fragmentedFlowPortionRect.x();
        LayoutUnit maxX = isLastPortion ? std::max(fragmentedFlowPortionRect.maxX(), fragmentedFlowOverflow.maxX()) : fragmentedFlowPortionRect.maxX();
        bool clipY = effectiveOverflowY() != Overflow::Visible;
        LayoutUnit minY = clipY ? fragmentedFlowPortionRect.y() : std::min(fragmentedFlowPortionRect.y(), fragmentedFlowOverflow.y());
        LayoutUnit maxY = clipY ? fragmentedFlowPortionRect.maxY() : std::max(fragmentedFlowPortionRect.y(), fragmentedFlowOverflow.maxY());
        clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
    }
    return clipRect;
}

LayoutUnit RenderFragmentContainer::pageLogicalTopForOffset(LayoutUnit /* offset */) const
{
    return fragmentedFlow()->isHorizontalWritingMode() ? fragmentedFlowPortionRect().y() : fragmentedFlowPortionRect().x();
}

bool RenderFragmentContainer::isFirstFragment() const
{
    ASSERT(isValid());

    return m_fragmentedFlow->firstFragment() == this;
}

bool RenderFragmentContainer::isLastFragment() const
{
    ASSERT(isValid());

    return m_fragmentedFlow->lastFragment() == this;
}

bool RenderFragmentContainer::shouldClipFragmentedFlowContent() const
{
    return hasNonVisibleOverflow();
}

void RenderFragmentContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    RenderBlockFlow::styleDidChange(diff, oldStyle);

    if (!isValid())
        return;

    if (oldStyle && oldStyle->writingMode() != style().writingMode())
        m_fragmentedFlow->fragmentChangedWritingMode(this);
}

void RenderFragmentContainer::computeOverflowFromFragmentedFlow()
{
    ASSERT(isValid());

    LayoutRect layoutRect = layoutOverflowRectForBox(m_fragmentedFlow);
    layoutRect.setLocation(contentBoxRect().location() + (layoutRect.location() - m_fragmentedFlowPortionRect.location()));

    // FIXME: Correctly adjust the layout overflow for writing modes.
    addLayoutOverflow(layoutRect);
    RenderFragmentedFlow* enclosingRenderFragmentedFlow = enclosingFragmentedFlow();
    if (enclosingRenderFragmentedFlow)
        enclosingRenderFragmentedFlow->addFragmentsLayoutOverflow(this, layoutRect);

    updateLayerTransform();
    updateScrollInfoAfterLayout();
}

void RenderFragmentContainer::repaintFragmentedFlowContent(const LayoutRect& repaintRect)
{
    repaintFragmentedFlowContentRectangle(repaintRect, fragmentedFlowPortionRect(), contentBoxRect().location());
}

void RenderFragmentContainer::repaintFragmentedFlowContentRectangle(const LayoutRect& repaintRect, const LayoutRect& fragmentedFlowPortionRect, const LayoutPoint& fragmentLocation, const LayoutRect* fragmentedFlowPortionClipRect)
{
    ASSERT(isValid());

    // We only have to issue a repaint in this fragment if the fragment rect intersects the repaint rect.
    LayoutRect clippedRect(repaintRect);

    if (fragmentedFlowPortionClipRect) {
        LayoutRect flippedFragmentedFlowPortionClipRect(*fragmentedFlowPortionClipRect);
        fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionClipRect);
        clippedRect.intersect(flippedFragmentedFlowPortionClipRect);
    }

    if (clippedRect.isEmpty())
        return;

    LayoutRect flippedFragmentedFlowPortionRect(fragmentedFlowPortionRect);
    fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionRect); // Put the fragment rects into physical coordinates.

    // Put the fragment rect into the fragment's physical coordinate space.
    clippedRect.setLocation(fragmentLocation + (clippedRect.location() - flippedFragmentedFlowPortionRect.location()));

    // Now switch to the fragment's writing mode coordinate space and let it repaint itself.
    flipForWritingMode(clippedRect);
    
    // Issue the repaint.
    repaintRectangle(clippedRect);
}

LayoutRect RenderFragmentContainer::fragmentedFlowContentRectangle(const LayoutRect& rect, const LayoutRect& fragmentedFlowPortionRect, const LayoutPoint& fragmentLocation, const LayoutRect* fragmentedFlowPortionClipRect)
{
    auto clippedRect = rect;

    if (fragmentedFlowPortionClipRect) {
        LayoutRect flippedFragmentedFlowPortionClipRect(*fragmentedFlowPortionClipRect);
        fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionClipRect);
        clippedRect.edgeInclusiveIntersect(flippedFragmentedFlowPortionClipRect); // edgeInclusiveIntersect to avoid rects with zero height or width becoming zero-sized.
    }

    LayoutRect flippedFragmentedFlowPortionRect(fragmentedFlowPortionRect);
    fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionRect);

    // Put the fragment rect into the fragment's physical coordinate space.
    clippedRect.setLocation(fragmentLocation + (clippedRect.location() - flippedFragmentedFlowPortionRect.location()));

    // Now switch to the fragment's writing mode coordinate space and let it repaint itself.
    flipForWritingMode(clippedRect);
    
    return clippedRect;
}

Vector<LayoutRect> RenderFragmentContainer::fragmentRectsForFlowContentRect(const LayoutRect& contentRect)
{
    auto portionRect = fragmentedFlowPortionRect();
    auto fragmentLocation = contentBoxRect().location();
    
    auto fragmentRect = contentRect;
    
    auto flippedFragmentedFlowPortionRect = portionRect;
    fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionRect);
    fragmentRect.setLocation(fragmentLocation + (fragmentRect.location() - flippedFragmentedFlowPortionRect.location()));

    flipForWritingMode(fragmentRect);

    return { fragmentRect };
}

void RenderFragmentContainer::installFragmentedFlow()
{
    ASSERT_NOT_REACHED();
}

void RenderFragmentContainer::attachFragment()
{
    if (renderTreeBeingDestroyed())
        return;
    
    // A fragment starts off invalid.
    setIsValid(false);

    // Initialize the flow thread reference and create the flow thread object if needed.
    // The flow thread lifetime is influenced by the number of fragments attached to it,
    // and we are attaching the fragment to the flow thread.
    installFragmentedFlow();
    
    if (!m_fragmentedFlow)
        return;

    // Only after adding the fragment to the thread, the fragment is marked to be valid.
    m_fragmentedFlow->addFragmentToThread(this);
}

void RenderFragmentContainer::detachFragment()
{
    if (m_fragmentedFlow)
        m_fragmentedFlow->removeFragmentFromThread(this);
    m_fragmentedFlow = nullptr;
}

RenderBoxFragmentInfo* RenderFragmentContainer::renderBoxFragmentInfo(const RenderBox* box) const
{
    ASSERT(isValid());
    return m_renderBoxFragmentInfo.get(box);
}

RenderBoxFragmentInfo* RenderFragmentContainer::setRenderBoxFragmentInfo(const RenderBox* box, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
    bool containingBlockChainIsInset)
{
    ASSERT(isValid());

    std::unique_ptr<RenderBoxFragmentInfo>& boxInfo = m_renderBoxFragmentInfo.add(box, makeUnique<RenderBoxFragmentInfo>(logicalLeftInset, logicalRightInset, containingBlockChainIsInset)).iterator->value;
    return boxInfo.get();
}

std::unique_ptr<RenderBoxFragmentInfo> RenderFragmentContainer::takeRenderBoxFragmentInfo(const RenderBox* box)
{
    return m_renderBoxFragmentInfo.take(box);
}

void RenderFragmentContainer::removeRenderBoxFragmentInfo(const RenderBox& box)
{
    m_renderBoxFragmentInfo.remove(&box);
}

void RenderFragmentContainer::deleteAllRenderBoxFragmentInfo()
{
    m_renderBoxFragmentInfo.clear();
}

LayoutUnit RenderFragmentContainer::logicalTopOfFragmentedFlowContentRect(const LayoutRect& rect) const
{
    ASSERT(isValid());
    return fragmentedFlow()->isHorizontalWritingMode() ? rect.y() : rect.x();
}

LayoutUnit RenderFragmentContainer::logicalBottomOfFragmentedFlowContentRect(const LayoutRect& rect) const
{
    ASSERT(isValid());
    return fragmentedFlow()->isHorizontalWritingMode() ? rect.maxY() : rect.maxX();
}

void RenderFragmentContainer::insertedIntoTree(IsInternalMove isInternalMove)
{
    attachFragment();
    if (isValid())
        RenderBlockFlow::insertedIntoTree(isInternalMove);
}

void RenderFragmentContainer::willBeRemovedFromTree(IsInternalMove isInternalMove)
{
    RenderBlockFlow::willBeRemovedFromTree(isInternalMove);

    detachFragment();
}

void RenderFragmentContainer::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
{
    if (!isValid()) {
        RenderBlockFlow::computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
        return;
    }

    minLogicalWidth = m_fragmentedFlow->minPreferredLogicalWidth();
    maxLogicalWidth = m_fragmentedFlow->maxPreferredLogicalWidth();
}

void RenderFragmentContainer::computePreferredLogicalWidths()
{
    ASSERT(preferredLogicalWidthsDirty());

    if (!isValid()) {
        RenderBlockFlow::computePreferredLogicalWidths();
        return;
    }

    // FIXME: Currently, the code handles only the <length> case for min-width/max-width.
    // It should also support other values, like percentage, calc or viewport relative.
    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;

    const RenderStyle& styleToUse = style();
    if (styleToUse.logicalWidth().isFixed() && styleToUse.logicalWidth().value() > 0)
        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalWidth());
    else
        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);

    RenderBox::computePreferredLogicalWidths(style().logicalMinWidth(), style().logicalMaxWidth(), borderAndPaddingLogicalWidth());

    setPreferredLogicalWidthsDirty(false);
}

// FIXME: Unused.
void RenderFragmentContainer::adjustFragmentBoundsFromFragmentedFlowPortionRect(LayoutRect& fragmentBounds) const
{
    LayoutRect flippedFragmentedFlowPortionRect = fragmentedFlowPortionRect();
    fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionRect);
    fragmentBounds.moveBy(flippedFragmentedFlowPortionRect.location());
}

void RenderFragmentContainer::ensureOverflowForBox(const RenderBox* box, RefPtr<RenderOverflow>& overflow, bool forceCreation)
{
    ASSERT(m_fragmentedFlow->renderFragmentContainerList().contains(this));
    ASSERT(isValid());

    RenderBoxFragmentInfo* boxInfo = renderBoxFragmentInfo(box);
    if (!boxInfo && !forceCreation)
        return;

    if (boxInfo && boxInfo->overflow()) {
        overflow = boxInfo->overflow();
        return;
    }
    
    LayoutRect borderBox = box->borderBoxRectInFragment(this);
    LayoutRect clientBox;
    ASSERT(m_fragmentedFlow->objectShouldFragmentInFlowFragment(box, this));

    if (!borderBox.isEmpty()) {
        borderBox = rectFlowPortionForBox(box, borderBox);
        
        clientBox = box->clientBoxRectInFragment(this);
        clientBox = rectFlowPortionForBox(box, clientBox);
        
        m_fragmentedFlow->flipForWritingModeLocalCoordinates(borderBox);
        m_fragmentedFlow->flipForWritingModeLocalCoordinates(clientBox);
    }

    if (boxInfo) {
        boxInfo->createOverflow(clientBox, borderBox);
        overflow = boxInfo->overflow();
    } else
        overflow = adoptRef(new RenderOverflow(clientBox, borderBox));
}

LayoutRect RenderFragmentContainer::rectFlowPortionForBox(const RenderBox* box, const LayoutRect& rect) const
{
    LayoutRect mappedRect = m_fragmentedFlow->mapFromLocalToFragmentedFlow(box, rect);

    RenderFragmentContainer* startFragment = nullptr;
    RenderFragmentContainer* endFragment = nullptr;
    if (m_fragmentedFlow->getFragmentRangeForBox(box, startFragment, endFragment)) {
        if (fragmentedFlow()->isHorizontalWritingMode()) {
            if (this != startFragment)
                mappedRect.shiftYEdgeTo(std::max<LayoutUnit>(logicalTopForFragmentedFlowContent(), mappedRect.y()));
            if (this != endFragment)
                mappedRect.setHeight(std::max<LayoutUnit>(0, std::min<LayoutUnit>(logicalBottomForFragmentedFlowContent() - mappedRect.y(), mappedRect.height())));
        } else {
            if (this != startFragment)
                mappedRect.shiftXEdgeTo(std::max<LayoutUnit>(logicalTopForFragmentedFlowContent(), mappedRect.x()));
            if (this != endFragment)
                mappedRect.setWidth(std::max<LayoutUnit>(0, std::min<LayoutUnit>(logicalBottomForFragmentedFlowContent() - mappedRect.x(), mappedRect.width())));
        }
    }

    return m_fragmentedFlow->mapFromFragmentedFlowToLocal(box, mappedRect);
}

void RenderFragmentContainer::addLayoutOverflowForBox(const RenderBox* box, const LayoutRect& rect)
{
    if (rect.isEmpty())
        return;

    RefPtr<RenderOverflow> fragmentOverflow;
    ensureOverflowForBox(box, fragmentOverflow, false);

    if (!fragmentOverflow)
        return;

    fragmentOverflow->addLayoutOverflow(rect);
}

void RenderFragmentContainer::addVisualOverflowForBox(const RenderBox* box, const LayoutRect& rect)
{
    if (rect.isEmpty())
        return;

    RefPtr<RenderOverflow> fragmentOverflow;
    ensureOverflowForBox(box, fragmentOverflow, false);

    if (!fragmentOverflow)
        return;

    LayoutRect flippedRect = rect;
    fragmentedFlow()->flipForWritingModeLocalCoordinates(flippedRect);
    fragmentOverflow->addVisualOverflow(flippedRect);
}

LayoutRect RenderFragmentContainer::layoutOverflowRectForBox(const RenderBox* box)
{
    RefPtr<RenderOverflow> overflow;
    ensureOverflowForBox(box, overflow, true);
    
    ASSERT(overflow);
    return overflow->layoutOverflowRect();
}

LayoutRect RenderFragmentContainer::visualOverflowRectForBox(const RenderBoxModelObject& box)
{
    if (is<RenderInline>(box)) {
        const RenderInline& inlineBox = downcast<RenderInline>(box);
        return inlineBox.linesVisualOverflowBoundingBoxInFragment(this);
    }

    if (is<RenderBox>(box)) {
        RefPtr<RenderOverflow> overflow;
        ensureOverflowForBox(&downcast<RenderBox>(box), overflow, true);

        ASSERT(overflow);
        return overflow->visualOverflowRect();
    }

    ASSERT_NOT_REACHED();
    return LayoutRect();
}

// FIXME: This doesn't work for writing modes.
LayoutRect RenderFragmentContainer::layoutOverflowRectForBoxForPropagation(const RenderBox* box)
{
    // Only propagate interior layout overflow if we don't clip it.
    LayoutRect rect = box->borderBoxRectInFragment(this);
    rect = rectFlowPortionForBox(box, rect);
    if (!box->hasNonVisibleOverflow())
        rect.unite(layoutOverflowRectForBox(box));

    bool hasTransform = box->hasTransform();
    if (box->isInFlowPositioned() || hasTransform) {
        if (hasTransform)
            rect = box->layer()->currentTransform().mapRect(rect);

        if (box->isInFlowPositioned())
            rect.move(box->offsetForInFlowPosition());
    }

    return rect;
}

LayoutRect RenderFragmentContainer::visualOverflowRectForBoxForPropagation(const RenderBoxModelObject& box)
{
    LayoutRect rect = visualOverflowRectForBox(box);
    fragmentedFlow()->flipForWritingModeLocalCoordinates(rect);

    return rect;
}

CurrentRenderFragmentContainerMaintainer::CurrentRenderFragmentContainerMaintainer(RenderFragmentContainer& fragment)
    : m_fragment(fragment)
{
    RenderFragmentedFlow* fragmentedFlow = fragment.fragmentedFlow();
    // A flow thread can have only one current fragment.
    ASSERT(!fragmentedFlow->currentFragment());
    fragmentedFlow->setCurrentFragmentMaintainer(this);
}

CurrentRenderFragmentContainerMaintainer::~CurrentRenderFragmentContainerMaintainer()
{
    RenderFragmentedFlow* fragmentedFlow = m_fragment.fragmentedFlow();
    fragmentedFlow->setCurrentFragmentMaintainer(nullptr);
}

#ifndef NDEBUG

TextStream& operator<<(TextStream& stream, const RenderFragmentContainer& container)
{
    return stream << &container;
}

#endif

} // namespace WebCore
