/*
 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
 *           (C) 1997 Torben Weis (weis@kde.org)
 *           (C) 1998 Waldo Bastian (bastian@kde.org)
 *           (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2013 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.
 */

#ifndef RenderTableCell_h
#define RenderTableCell_h

#include "core/rendering/RenderBlockFlow.h"
#include "core/rendering/RenderTableRow.h"
#include "core/rendering/RenderTableSection.h"
#include "platform/LengthFunctions.h"

namespace blink {

static const unsigned unsetColumnIndex = 0x1FFFFFFF;
static const unsigned maxColumnIndex = 0x1FFFFFFE; // 536,870,910

enum IncludeBorderColorOrNot { DoNotIncludeBorderColor, IncludeBorderColor };

class SubtreeLayoutScope;

class RenderTableCell final : public RenderBlockFlow {
public:
    explicit RenderTableCell(Element*);

    unsigned colSpan() const
    {
        if (!m_hasColSpan)
            return 1;
        return parseColSpanFromDOM();
    }
    unsigned rowSpan() const
    {
        if (!m_hasRowSpan)
            return 1;
        return parseRowSpanFromDOM();
    }

    // Called from HTMLTableCellElement.
    void colSpanOrRowSpanChanged();

    void setCol(unsigned column)
    {
        if (UNLIKELY(column > maxColumnIndex))
            CRASH();

        m_column = column;
    }

    unsigned col() const
    {
        ASSERT(m_column != unsetColumnIndex);
        return m_column;
    }

    RenderTableRow* row() const { return toRenderTableRow(parent()); }
    RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
    RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }

    RenderTableCell* previousCell() const;
    RenderTableCell* nextCell() const;

    unsigned rowIndex() const
    {
        // This function shouldn't be called on a detached cell.
        ASSERT(row());
        return row()->rowIndex();
    }

    Length styleOrColLogicalWidth() const
    {
        Length styleWidth = style()->logicalWidth();
        if (!styleWidth.isAuto())
            return styleWidth;
        if (RenderTableCol* firstColumn = table()->colElement(col()))
            return logicalWidthFromColumns(firstColumn, styleWidth);
        return styleWidth;
    }

    int logicalHeightForRowSizing() const
    {
        // FIXME: This function does too much work, and is very hot during table layout!
        int adjustedLogicalHeight = pixelSnappedLogicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
        int styleLogicalHeight = valueForLength(style()->logicalHeight(), 0);
        // In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
        // Call computedCSSPadding* directly to avoid including implicitPadding.
        if (!document().inQuirksMode() && style()->boxSizing() != BORDER_BOX)
            styleLogicalHeight += (computedCSSPaddingBefore() + computedCSSPaddingAfter()).floor() + borderBefore() + borderAfter();
        return max(styleLogicalHeight, adjustedLogicalHeight);
    }


    void setCellLogicalWidth(int constrainedLogicalWidth, SubtreeLayoutScope&);

    virtual int borderLeft() const override;
    virtual int borderRight() const override;
    virtual int borderTop() const override;
    virtual int borderBottom() const override;
    virtual int borderStart() const override;
    virtual int borderEnd() const override;
    virtual int borderBefore() const override;
    virtual int borderAfter() const override;

    void collectBorderValues(RenderTable::CollapsedBorderValues&) const;
    static void sortBorderValues(RenderTable::CollapsedBorderValues&);

    virtual void layout() override;

    virtual void paint(PaintInfo&, const LayoutPoint&) override;

    void paintCollapsedBorders(PaintInfo&, const LayoutPoint&);
    void paintBackgroundsBehindCell(PaintInfo&, const LayoutPoint&, RenderObject* backgroundObject);

    LayoutUnit cellBaselinePosition() const;
    bool isBaselineAligned() const
    {
        EVerticalAlign va = style()->verticalAlign();
        return va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB || va == LENGTH;
    }

    void computeIntrinsicPadding(int rowHeight, SubtreeLayoutScope&);
    void clearIntrinsicPadding() { setIntrinsicPadding(0, 0); }

    int intrinsicPaddingBefore() const { return m_intrinsicPaddingBefore; }
    int intrinsicPaddingAfter() const { return m_intrinsicPaddingAfter; }

    virtual LayoutUnit paddingTop() const override;
    virtual LayoutUnit paddingBottom() const override;
    virtual LayoutUnit paddingLeft() const override;
    virtual LayoutUnit paddingRight() const override;

    // FIXME: For now we just assume the cell has the same block flow direction as the table. It's likely we'll
    // create an extra anonymous RenderBlock to handle mixing directionality anyway, in which case we can lock
    // the block flow directionality of the cells to the table's directionality.
    virtual LayoutUnit paddingBefore() const override;
    virtual LayoutUnit paddingAfter() const override;

    void setOverrideLogicalContentHeightFromRowHeight(LayoutUnit);

    virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged) override;

    bool cellWidthChanged() const { return m_cellWidthChanged; }
    void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }

    static RenderTableCell* createAnonymous(Document*);
    static RenderTableCell* createAnonymousWithParentRenderer(const RenderObject*);
    virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const override
    {
        return createAnonymousWithParentRenderer(parent);
    }

    // This function is used to unify which table part's style we use for computing direction and
    // writing mode. Writing modes are not allowed on row group and row but direction is.
    // This means we can safely use the same style in all cases to simplify our code.
    // FIXME: Eventually this function should replaced by style() once we support direction
    // on all table parts and writing-mode on cells.
    const RenderStyle* styleForCellFlow() const
    {
        return row()->style();
    }

    const BorderValue& borderAdjoiningTableStart() const
    {
        ASSERT(isFirstOrLastCellInRow());
        if (section()->hasSameDirectionAs(table()))
            return style()->borderStart();

        return style()->borderEnd();
    }

    const BorderValue& borderAdjoiningTableEnd() const
    {
        ASSERT(isFirstOrLastCellInRow());
        if (section()->hasSameDirectionAs(table()))
            return style()->borderEnd();

        return style()->borderStart();
    }

    const BorderValue& borderAdjoiningCellBefore(const RenderTableCell* cell)
    {
        ASSERT_UNUSED(cell, table()->cellAfter(cell) == this);
        // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
        return style()->borderStart();
    }

    const BorderValue& borderAdjoiningCellAfter(const RenderTableCell* cell)
    {
        ASSERT_UNUSED(cell, table()->cellBefore(cell) == this);
        // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
        return style()->borderEnd();
    }

#if ENABLE(ASSERT)
    bool isFirstOrLastCellInRow() const
    {
        return !table()->cellAfter(this) || !table()->cellBefore(this);
    }
#endif
protected:
    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
    virtual void computePreferredLogicalWidths() override;

    virtual void addLayerHitTestRects(LayerHitTestRects&, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset, const LayoutRect& containerRect) const override;

private:
    virtual const char* renderName() const override { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }

    virtual bool isOfType(RenderObjectType type) const override { return type == RenderObjectTableCell || RenderBlockFlow::isOfType(type); }

    virtual void willBeRemovedFromTree() override;

    virtual void updateLogicalWidth() override;

    virtual void paintBoxDecorationBackground(PaintInfo&, const LayoutPoint&) override;
    virtual void paintMask(PaintInfo&, const LayoutPoint&) override;

    virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const override;

    virtual LayoutSize offsetFromContainer(const RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const override;
    virtual LayoutRect clippedOverflowRectForPaintInvalidation(const RenderLayerModelObject* paintInvalidationContainer, const PaintInvalidationState* = 0) const override;
    virtual void mapRectToPaintInvalidationBacking(const RenderLayerModelObject* paintInvalidationContainer, LayoutRect&, const PaintInvalidationState*) const override;

    int borderHalfLeft(bool outer) const;
    int borderHalfRight(bool outer) const;
    int borderHalfTop(bool outer) const;
    int borderHalfBottom(bool outer) const;

    int borderHalfStart(bool outer) const;
    int borderHalfEnd(bool outer) const;
    int borderHalfBefore(bool outer) const;
    int borderHalfAfter(bool outer) const;

    void setIntrinsicPaddingBefore(int p) { m_intrinsicPaddingBefore = p; }
    void setIntrinsicPaddingAfter(int p) { m_intrinsicPaddingAfter = p; }
    void setIntrinsicPadding(int before, int after) { setIntrinsicPaddingBefore(before); setIntrinsicPaddingAfter(after); }

    bool hasStartBorderAdjoiningTable() const;
    bool hasEndBorderAdjoiningTable() const;

    CollapsedBorderValue collapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    CollapsedBorderValue collapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    CollapsedBorderValue collapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    CollapsedBorderValue collapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;

    CollapsedBorderValue cachedCollapsedLeftBorder(const RenderStyle*) const;
    CollapsedBorderValue cachedCollapsedRightBorder(const RenderStyle*) const;
    CollapsedBorderValue cachedCollapsedTopBorder(const RenderStyle*) const;
    CollapsedBorderValue cachedCollapsedBottomBorder(const RenderStyle*) const;

    CollapsedBorderValue computeCollapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    CollapsedBorderValue computeCollapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    CollapsedBorderValue computeCollapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
    CollapsedBorderValue computeCollapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;

    Length logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const;

    void updateColAndRowSpanFlags();

    unsigned parseRowSpanFromDOM() const;
    unsigned parseColSpanFromDOM() const;

    void nextSibling() const WTF_DELETED_FUNCTION;
    void previousSibling() const WTF_DELETED_FUNCTION;

    // Note MSVC will only pack members if they have identical types, hence we use unsigned instead of bool here.
    unsigned m_column : 29;
    unsigned m_cellWidthChanged : 1;
    unsigned m_hasColSpan: 1;
    unsigned m_hasRowSpan: 1;
    int m_intrinsicPaddingBefore;
    int m_intrinsicPaddingAfter;
};

DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderTableCell, isTableCell());

inline RenderTableCell* RenderTableCell::previousCell() const
{
    return toRenderTableCell(RenderObject::previousSibling());
}

inline RenderTableCell* RenderTableCell::nextCell() const
{
    return toRenderTableCell(RenderObject::nextSibling());
}

inline RenderTableCell* RenderTableRow::firstCell() const
{
    ASSERT(children() == virtualChildren());
    return toRenderTableCell(children()->firstChild());
}

inline RenderTableCell* RenderTableRow::lastCell() const
{
    ASSERT(children() == virtualChildren());
    return toRenderTableCell(children()->lastChild());
}

} // namespace blink

#endif // RenderTableCell_h
