/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrShape_DEFINED
#define GrShape_DEFINED

#include "GrStyle.h"
#include "SkPath.h"
#include "SkPathPriv.h"
#include "SkRRect.h"
#include "SkTemplates.h"
#include "SkTLazy.h"

/**
 * Represents a geometric shape (rrect or path) and the GrStyle that it should be rendered with.
 * It is possible to apply the style to the GrShape to produce a new GrShape where the geometry
 * reflects the styling information (e.g. is stroked). It is also possible to apply just the
 * path effect from the style. In this case the resulting shape will include any remaining
 * stroking information that is to be applied after the path effect.
 *
 * Shapes can produce keys that represent only the geometry information, not the style. Note that
 * when styling information is applied to produce a new shape then the style has been converted
 * to geometric information and is included in the new shape's key. When the same style is applied
 * to two shapes that reflect the same underlying geometry the computed keys of the stylized shapes
 * will be the same.
 *
 * Currently this can only be constructed from a path, rect, or rrect though it can become a path
 * applying style to the geometry. The idea is to expand this to cover most or all of the geometries
 * that have SkCanvas::draw APIs.
 */
class GrShape {
public:
    GrShape() : fType(Type::kEmpty) {}

    explicit GrShape(const SkPath& path)
        : fType(Type::kPath)
        , fPath(&path) {
        this->attemptToReduceFromPath();
    }

    explicit GrShape(const SkRRect& rrect)
        : fType(Type::kRRect)
        , fRRect(rrect)
        , fRRectIsInverted(false) {
        fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir);
        this->attemptToReduceFromRRect();
    }

    explicit GrShape(const SkRect& rect)
        : fType(Type::kRRect)
        , fRRect(SkRRect::MakeRect(rect))
        , fRRectIsInverted(false) {
        fRRectStart = DefaultRectDirAndStartIndex(rect, false, &fRRectDir);
        this->attemptToReduceFromRRect();
    }

    GrShape(const SkPath& path, const GrStyle& style)
        : fType(Type::kPath)
        , fPath(&path)
        , fStyle(style) {
        this->attemptToReduceFromPath();
    }

    GrShape(const SkRRect& rrect, const GrStyle& style)
        : fType(Type::kRRect)
        , fRRect(rrect)
        , fRRectIsInverted(false)
        , fStyle(style) {
        fRRectStart = DefaultRRectDirAndStartIndex(rrect, style.hasPathEffect(), &fRRectDir);
        this->attemptToReduceFromRRect();
    }

    GrShape(const SkRRect& rrect, SkPath::Direction dir, unsigned start, bool inverted,
            const GrStyle& style)
        : fType(Type::kRRect)
        , fRRect(rrect)
        , fRRectIsInverted(inverted)
        , fStyle(style) {
        if (style.pathEffect()) {
            fRRectDir = dir;
            fRRectStart = start;
            if (fRRect.getType() == SkRRect::kRect_Type) {
                fRRectStart = (fRRectStart + 1) & 0b110;
            } else if (fRRect.getType() == SkRRect::kOval_Type) {
                fRRectStart &= 0b110;
            }
        } else {
            fRRectStart = DefaultRRectDirAndStartIndex(rrect, false, &fRRectDir);
        }
        this->attemptToReduceFromRRect();
    }

    GrShape(const SkRect& rect, const GrStyle& style)
        : fType(Type::kRRect)
        , fRRect(SkRRect::MakeRect(rect))
        , fRRectIsInverted(false)
        , fStyle(style) {
        fRRectStart = DefaultRectDirAndStartIndex(rect, style.hasPathEffect(), &fRRectDir);
        this->attemptToReduceFromRRect();
    }

    GrShape(const SkPath& path, const SkPaint& paint)
        : fType(Type::kPath)
        , fPath(&path)
        , fStyle(paint) {
        this->attemptToReduceFromPath();
    }

    GrShape(const SkRRect& rrect, const SkPaint& paint)
        : fType(Type::kRRect)
        , fRRect(rrect)
        , fRRectIsInverted(false)
        , fStyle(paint) {
        fRRectStart = DefaultRRectDirAndStartIndex(rrect, fStyle.hasPathEffect(), &fRRectDir);
        this->attemptToReduceFromRRect();
    }

    GrShape(const SkRect& rect, const SkPaint& paint)
        : fType(Type::kRRect)
        , fRRect(SkRRect::MakeRect(rect))
        , fRRectIsInverted(false)
        , fStyle(paint) {
        fRRectStart = DefaultRectDirAndStartIndex(rect, fStyle.hasPathEffect(), &fRRectDir);
        this->attemptToReduceFromRRect();
    }

    GrShape(const GrShape&);
    GrShape& operator=(const GrShape& that);

    ~GrShape() {
        if (Type::kPath == fType) {
            fPath.reset();
        }
    }

    const GrStyle& style() const { return fStyle; }

    /**
     * Returns a shape that has either applied the path effect or path effect and stroking
     * information from this shape's style to its geometry. Scale is used when approximating the
     * output geometry and typically is computed from the view matrix
     */
    GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) {
        return GrShape(*this, apply, scale);
    }

    /** Returns the unstyled geometry as a rrect if possible. */
    bool asRRect(SkRRect* rrect, SkPath::Direction* dir, unsigned* start, bool* inverted) const {
        if (Type::kRRect != fType) {
            return false;
        }
        if (rrect) {
            *rrect = fRRect;
        }
        if (dir) {
            *dir = fRRectDir;
        }
        if (start) {
            *start = fRRectStart;
        }
        if (inverted) {
            *inverted = fRRectIsInverted;
        }
        return true;
    }

    /**
     * If the unstyled shape is a straight line segment, returns true and sets pts to the endpoints.
     * An inverse filled line path is still considered a line.
     */
     bool asLine(SkPoint pts[2]) const {
         if (fType != Type::kPath) {
             return false;
         }
         return fPath.get()->isLine(pts);
     }

    /** Returns the unstyled geometry as a path. */
    void asPath(SkPath* out) const {
        switch (fType) {
            case Type::kEmpty:
                out->reset();
                break;
            case Type::kRRect:
                out->reset();
                out->addRRect(fRRect, fRRectDir, fRRectStart);
                if (fRRectIsInverted) {
                    out->setFillType(SkPath::kInverseWinding_FillType);
                }
                break;
            case Type::kPath:
                *out = *fPath.get();
                break;
        }
    }

    /**
     * Returns whether the geometry is empty. Note that applying the style could produce a
     * non-empty shape.
     */
    bool isEmpty() const { return Type::kEmpty == fType; }

    /**
     * Gets the bounds of the geometry without reflecting the shape's styling. This ignores
     * the inverse fill nature of the geometry.
     */
    const SkRect& bounds() const;

    /**
     * Gets the bounds of the geometry reflecting the shape's styling (ignoring inverse fill
     * status).
     */
    void styledBounds(SkRect* bounds) const;

    /**
     * Is it known that the unstyled geometry has no unclosed contours. This means that it will
     * not have any caps if stroked (modulo the effect of any path effect).
     */
    bool knownToBeClosed() const {
        switch (fType) {
            case Type::kEmpty:
                return true;
            case Type::kRRect:
                return true;
            case Type::kPath:
                return false;
        }
        return false;
    }

    uint32_t segmentMask() const {
        switch (fType) {
            case Type::kEmpty:
                return 0;
            case Type::kRRect:
                if (fRRect.getType() == SkRRect::kOval_Type) {
                    return SkPath::kConic_SegmentMask;
                } else if (fRRect.getType() == SkRRect::kRect_Type) {
                    return SkPath::kLine_SegmentMask;
                }
                return SkPath::kLine_SegmentMask | SkPath::kConic_SegmentMask;
            case Type::kPath:
                return fPath.get()->getSegmentMasks();
        }
        return 0;
    }

    /**
     * Gets the size of the key for the shape represented by this GrShape (ignoring its styling).
     * A negative value is returned if the shape has no key (shouldn't be cached).
     */
    int unstyledKeySize() const;

    /**
     * Writes unstyledKeySize() bytes into the provided pointer. Assumes that there is enough
     * space allocated for the key and that unstyledKeySize() does not return a negative value
     * for this shape.
     */
    void writeUnstyledKey(uint32_t* key) const;

private:
    enum class Type {
        kEmpty,
        kRRect,
        kPath,
    };

    /** Constructor used by the applyStyle() function */
    GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);

    /**
     * Determines the key we should inherit from the input shape's geometry and style when
     * we are applying the style to create a new shape.
     */
    void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);

    void attemptToReduceFromPath() {
        SkASSERT(Type::kPath == fType);
        fType = AttemptToReduceFromPathImpl(*fPath.get(), &fRRect, &fRRectDir, &fRRectStart,
                                            &fRRectIsInverted, fStyle.pathEffect(),
                                            fStyle.strokeRec());
        if (Type::kPath != fType) {
            fPath.reset();
            fInheritedKey.reset(0);
        }
    }

    void attemptToReduceFromRRect() {
        SkASSERT(Type::kRRect == fType);
        SkASSERT(!fInheritedKey.count());
        if (fRRectIsInverted) {
            if (fStyle.isDashed()) {
                // Dashing ignores the inverseness (currently). skbug.com/5421
                fRRectIsInverted = false;
            }
        } else if (fRRect.isEmpty()) {
            fType = Type::kEmpty;
        }
    }

    static Type AttemptToReduceFromPathImpl(const SkPath& path, SkRRect* rrect,
                                            SkPath::Direction* rrectDir, unsigned* rrectStart,
                                            bool* rrectIsInverted, const SkPathEffect* pe,
                                            const SkStrokeRec& strokeRec);

    static constexpr SkPath::Direction kDefaultRRectDir = SkPath::kCW_Direction;
    static constexpr unsigned kDefaultRRectStart = 0;

    static unsigned DefaultRectDirAndStartIndex(const SkRect& rect, bool hasPathEffect,
                                                SkPath::Direction* dir) {
        *dir = kDefaultRRectDir;
        // This comes from SkPath's interface. The default for adding a SkRect is counter clockwise
        // beginning at index 0 (which happens to correspond to rrect index 0 or 7).
        if (!hasPathEffect) {
            // It doesn't matter what start we use, just be consistent to avoid redundant keys.
            return kDefaultRRectStart;
        }
        // In SkPath a rect starts at index 0 by default. This is the top left corner. However,
        // we store rects as rrects. RRects don't preserve the invertedness, but rather sort the
        // rect edges. Thus, we may need to modify the rrect's start index to account for the sort.
        bool swapX = rect.fLeft > rect.fRight;
        bool swapY = rect.fTop > rect.fBottom;
        if (swapX && swapY) {
            // 0 becomes start index 2 and times 2 to convert from rect the rrect indices.
            return 2 * 2;
        } else if (swapX) {
            *dir = SkPath::kCCW_Direction;
            // 0 becomes start index 1 and times 2 to convert from rect the rrect indices.
            return 2 * 1;
        } else if (swapY) {
            *dir = SkPath::kCCW_Direction;
            // 0 becomes start index 3 and times 2 to convert from rect the rrect indices.
            return 2 * 3;
        }
        return 0;
    }

    static unsigned DefaultRRectDirAndStartIndex(const SkRRect& rrect, bool hasPathEffect,
                                                 SkPath::Direction* dir) {
        // This comes from SkPath's interface. The default for adding a SkRRect to a path is
        // clockwise beginning at starting index 6.
        static constexpr unsigned kPathRRectStartIdx = 6;
        *dir = kDefaultRRectDir;
        if (!hasPathEffect) {
            // It doesn't matter what start we use, just be consistent to avoid redundant keys.
            return kDefaultRRectStart;
        }
        return kPathRRectStartIdx;
    }

    Type                        fType;
    SkRRect                     fRRect;
    SkPath::Direction           fRRectDir;
    unsigned                    fRRectStart;
    bool                        fRRectIsInverted;
    SkTLazy<SkPath>             fPath;
    GrStyle                     fStyle;
    SkAutoSTArray<8, uint32_t>  fInheritedKey;
};
#endif
