/*
 * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
 * Copyright (C) 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.
 *
 */

#pragma once

#include "RenderBoxModelObject.h"

namespace WebCore {

class InlineElementBox;
class HTMLElement;
class Position;

class RenderLineBreak final : public RenderBoxModelObject {
    WTF_MAKE_ISO_ALLOCATED(RenderLineBreak);
public:
    RenderLineBreak(HTMLElement&, RenderStyle&&);
    virtual ~RenderLineBreak();

    // FIXME: The lies here keep render tree dump based test results unchanged.
    const char* renderName() const override { return m_isWBR ? "RenderWordBreak" : "RenderBR"; }

    bool isWBR() const override { return m_isWBR; }

    std::unique_ptr<InlineElementBox> createInlineBox();
    InlineElementBox* inlineBoxWrapper() const { return m_inlineBoxWrapper; }
    void setInlineBoxWrapper(InlineElementBox*);
    void deleteInlineBoxWrapper();
    void replaceInlineBoxWrapper(InlineElementBox&);
    void dirtyLineBoxes(bool fullLayout);
    void deleteLineBoxesBeforeSimpleLineLayout();

    IntRect linesBoundingBox() const;

    void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const override;
    void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const override;
#if PLATFORM(IOS_FAMILY)
void collectSelectionRects(Vector<SelectionRect>&, unsigned startOffset = 0, unsigned endOffset = std::numeric_limits<unsigned>::max()) override;
#endif
    void ensureLineBoxes();

private:
    void node() const = delete;

    bool canHaveChildren() const override { return false; }
    void paint(PaintInfo&, const LayoutPoint&) override { }

    VisiblePosition positionForPoint(const LayoutPoint&, const RenderFragmentContainer*) override;
    int caretMinOffset() const override;
    int caretMaxOffset() const override;
    bool canBeSelectionLeaf() const override;
    LayoutRect localCaretRect(InlineBox*, unsigned caretOffset, LayoutUnit* extraWidthToEndOfLine) override;
    void setSelectionState(SelectionState) override;

    LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode) const override;
    int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode) const override;

    LayoutUnit marginTop() const override { return 0; }
    LayoutUnit marginBottom() const override { return 0; }
    LayoutUnit marginLeft() const override { return 0; }
    LayoutUnit marginRight() const override { return 0; }
    LayoutUnit marginBefore(const RenderStyle*) const override { return 0; }
    LayoutUnit marginAfter(const RenderStyle*) const override { return 0; }
    LayoutUnit marginStart(const RenderStyle*) const override { return 0; }
    LayoutUnit marginEnd(const RenderStyle*) const override { return 0; }
    LayoutUnit offsetWidth() const override { return linesBoundingBox().width(); }
    LayoutUnit offsetHeight() const override { return linesBoundingBox().height(); }
    LayoutRect borderBoundingBox() const override { return LayoutRect(LayoutPoint(), linesBoundingBox().size()); }
    LayoutRect frameRectForStickyPositioning() const override { ASSERT_NOT_REACHED(); return LayoutRect(); }
    LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const override { return LayoutRect(); }

    void updateFromStyle() override;
    bool requiresLayer() const override { return false; }

    InlineElementBox* m_inlineBoxWrapper;
    mutable int m_cachedLineHeight;
    bool m_isWBR;
};

} // namespace WebCore

SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderLineBreak, isLineBreak())
