/*
 * Copyright (C) 2010 Alex Milowski (alex@milowski.com). All rights reserved.
 * Copyright (C) 2016 Igalia S.L.
 *
 * 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 HOLDERS AND CONTRIBUTORS
 * "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
 * OWNER OR CONTRIBUTORS 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 "RenderMathMLRow.h"

#if ENABLE(MATHML)

#include "MathMLNames.h"
#include "MathMLRowElement.h"
#include "RenderIterator.h"
#include "RenderMathMLOperator.h"
#include "RenderMathMLRoot.h"
#include <wtf/IsoMallocInlines.h>

namespace WebCore {

using namespace MathMLNames;

WTF_MAKE_ISO_ALLOCATED_IMPL(RenderMathMLRow);

RenderMathMLRow::RenderMathMLRow(MathMLRowElement& element, RenderStyle&& style)
    : RenderMathMLBlock(element, WTFMove(style))
{
}

MathMLRowElement& RenderMathMLRow::element() const
{
    return static_cast<MathMLRowElement&>(nodeForNonAnonymous());
}

std::optional<LayoutUnit> RenderMathMLRow::firstLineBaseline() const
{
    auto* baselineChild = firstChildBox();
    if (!baselineChild)
        return std::optional<LayoutUnit>();

    return LayoutUnit { static_cast<int>(lroundf(ascentForChild(*baselineChild) + baselineChild->logicalTop())) };
}

static RenderMathMLOperator* toVerticalStretchyOperator(RenderBox* box)
{
    if (is<RenderMathMLBlock>(box)) {
        auto* renderOperator = downcast<RenderMathMLBlock>(*box).unembellishedOperator();
        if (renderOperator && renderOperator->isStretchy() && renderOperator->isVertical())
            return renderOperator;
    }
    return nullptr;
}

void RenderMathMLRow::stretchVerticalOperatorsAndLayoutChildren()
{
    // First calculate stretch ascent and descent.
    LayoutUnit stretchAscent, stretchDescent;
    for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        if (child->isOutOfFlowPositioned()) {
            child->containingBlock()->insertPositionedObject(*child);
            continue;
        }
        if (toVerticalStretchyOperator(child))
            continue;
        child->layoutIfNeeded();
        LayoutUnit childAscent = ascentForChild(*child);
        LayoutUnit childDescent = child->logicalHeight() - childAscent;
        stretchAscent = std::max(stretchAscent, childAscent);
        stretchDescent = std::max(stretchDescent, childDescent);
    }
    if (stretchAscent + stretchDescent <= 0) {
        // We ensure a minimal stretch size.
        stretchAscent = style().computedFontPixelSize();
        stretchDescent = 0;
    }

    // Next, we stretch the vertical operators.
    for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        if (child->isOutOfFlowPositioned())
            continue;
        if (auto renderOperator = toVerticalStretchyOperator(child)) {
            renderOperator->stretchTo(stretchAscent, stretchDescent);
            renderOperator->layoutIfNeeded();
            child->layoutIfNeeded();
        }
    }
}

void RenderMathMLRow::getContentBoundingBox(LayoutUnit& width, LayoutUnit& ascent, LayoutUnit& descent) const
{
    ascent = 0;
    descent = 0;
    width = borderAndPaddingStart();
    for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        if (child->isOutOfFlowPositioned())
            continue;

        width += child->marginStart() + child->logicalWidth() + child->marginEnd();
        LayoutUnit childAscent = ascentForChild(*child);
        LayoutUnit childDescent = child->logicalHeight() - childAscent;
        ascent = std::max(ascent, childAscent + child->marginTop());
        descent = std::max(descent, childDescent + child->marginBottom());
    }
    width += borderEnd() + paddingEnd();
}

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

    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;

    LayoutUnit preferredWidth;
    for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        if (child->isOutOfFlowPositioned())
            continue;
        preferredWidth += child->maxPreferredLogicalWidth() + child->marginLogicalWidth();
    }

    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = preferredWidth + borderAndPaddingLogicalWidth();

    setPreferredLogicalWidthsDirty(false);
}

void RenderMathMLRow::layoutRowItems(LayoutUnit width, LayoutUnit ascent)
{
    LayoutUnit horizontalOffset = borderAndPaddingStart();
    for (auto* child = firstChildBox(); child; child = child->nextSiblingBox()) {
        if (child->isOutOfFlowPositioned())
            continue;
        horizontalOffset += child->marginStart();
        LayoutUnit childAscent = ascentForChild(*child);
        LayoutUnit childVerticalOffset = borderTop() + paddingTop() + child->marginTop() + ascent - childAscent;
        LayoutUnit childWidth = child->logicalWidth();
        LayoutUnit childHorizontalOffset = style().isLeftToRightDirection() ? horizontalOffset : width - horizontalOffset - childWidth;
        child->setLocation(LayoutPoint(childHorizontalOffset, childVerticalOffset));
        horizontalOffset += childWidth + child->marginEnd();
    }
}

void RenderMathMLRow::layoutBlock(bool relayoutChildren, LayoutUnit)
{
    ASSERT(needsLayout());

    if (!relayoutChildren && simplifiedLayout())
        return;

    recomputeLogicalWidth();

    setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight());

    LayoutUnit width, ascent, descent;
    stretchVerticalOperatorsAndLayoutChildren();
    getContentBoundingBox(width, ascent, descent);
    layoutRowItems(width, ascent);
    setLogicalWidth(width);
    setLogicalHeight(borderTop() + paddingTop() + ascent + descent + borderBottom() + paddingBottom() + horizontalScrollbarHeight());
    updateLogicalHeight();

    layoutPositionedObjects(relayoutChildren);

    updateScrollInfoAfterLayout();

    clearNeedsLayout();
}

}

#endif // ENABLE(MATHML)
