// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BoxBorderPainter_h
#define BoxBorderPainter_h

#include "core/layout/BackgroundBleedAvoidance.h"
#include "core/style/BorderEdge.h"
#include "platform/geometry/FloatRoundedRect.h"

namespace blink {

class ComputedStyle;
class GraphicsContext;
class IntRect;
class LayoutBox;
class LayoutRect;
struct PaintInfo;
class Path;

typedef unsigned BorderEdgeFlags;

class BoxBorderPainter {
    STACK_ALLOCATED();
public:
    BoxBorderPainter(const LayoutRect& borderRect, const ComputedStyle&,
        BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);

    BoxBorderPainter(const ComputedStyle&, const LayoutRect& outer, const LayoutRect& inner,
        const BorderEdge& uniformEdgeInfo);

    void paintBorder(const PaintInfo&, const LayoutRect& borderRect) const;

private:
    struct ComplexBorderInfo;
    enum MiterType {
        NoMiter,
        SoftMiter, // Anti-aliased
        HardMiter, // Not anti-aliased
    };

    void computeBorderProperties();

    BorderEdgeFlags paintOpacityGroup(GraphicsContext&, const ComplexBorderInfo&, unsigned index,
        float accumulatedOpacity) const;
    void paintSide(GraphicsContext&, const ComplexBorderInfo&, BoxSide, unsigned alpha, BorderEdgeFlags) const;
    void paintOneBorderSide(GraphicsContext&, const FloatRect& sideRect, BoxSide, BoxSide adjacentSide1,
        BoxSide adjacentSide2, const Path*, bool antialias, Color, BorderEdgeFlags) const;
    bool paintBorderFastPath(GraphicsContext&, const LayoutRect& borderRect) const;
    void drawDoubleBorder(GraphicsContext&, const LayoutRect& borderRect) const;

    void drawBoxSideFromPath(GraphicsContext&, const LayoutRect&, const Path&, float thickness,
        float drawThickness, BoxSide, Color, EBorderStyle) const;
    void clipBorderSidePolygon(GraphicsContext&, BoxSide, MiterType miter1, MiterType miter2) const;
    void clipBorderSideForComplexInnerPath(GraphicsContext&, BoxSide) const;

    MiterType computeMiter(BoxSide, BoxSide adjacentSide, BorderEdgeFlags, bool antialias) const;
    static bool mitersRequireClipping(MiterType miter1, MiterType miter2, EBorderStyle, bool antialias);

    const BorderEdge& firstEdge() const
    {
        ASSERT(m_visibleEdgeSet);
        return m_edges[m_firstVisibleEdge];
    }

    // const inputs
    const ComputedStyle& m_style;
    const BackgroundBleedAvoidance m_bleedAvoidance;
    const bool m_includeLogicalLeftEdge;
    const bool m_includeLogicalRightEdge;

    // computed attributes
    FloatRoundedRect m_outer;
    FloatRoundedRect m_inner;
    BorderEdge m_edges[4];

    unsigned m_visibleEdgeCount;
    unsigned m_firstVisibleEdge;
    BorderEdgeFlags m_visibleEdgeSet;

    bool m_isUniformStyle;
    bool m_isUniformWidth;
    bool m_isUniformColor;
    bool m_isRounded;
    bool m_hasAlpha;
};

} // namespace blink

#endif
