/*
 * Copyright 2020 Google LLC
 *
 * 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 "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"

// Represents an arc along an oval boundary, or a closed wedge of the oval.
struct GrArc {
    SkRect   fOval;       // The sorted, bounding box defining the oval the arc is traced along
    SkScalar fStartAngle; // In degrees
    SkScalar fSweepAngle; // In degrees
    bool     fUseCenter;  // True if the arc includes the center point of the oval
};

// Represents a line segment between two points.
struct GrLineSegment {
    SkPoint fP1;
    SkPoint fP2;
};

/**
 * GrShape is a convenience class to represent the many different specialized geometries that
 * Ganesh can handle, including rects, round rects, lines, as well as paths. It is intended as
 * a data-only class where any additional complex behavior is handled by an owning type (e.g.
 * GrStyledShape). However, it does include some basic utilities that unify common functionality
 * (such as contains()) from the underlying shape types.
 *
 * In order to have lossless simplification of the geometry, it also tracks winding direction, start
 * index, and fill inversion. The direction and index are match the SkPath indexing scheme for
 * the shape's type (e.g. rect, rrect, or oval).
 *
 * Regarding GrShape's empty shape:
 * - GrShape uses empty to refer to the absence of any geometric data
 * - SkRect::isEmpty() returns true if the rect is not sorted, even if it has area. GrShape will not
 *   simplify these shapes to an empty GrShape. Rects with actual 0 width and height will simplify
 *   to a point or line, not empty. This is to preserve geometric data for path effects and strokes.
 * - SkRRect::isEmpty() is true when the bounds have 0 width or height, so GrShape will simplify it
 *   to a point or line, just like a rect. SkRRect does not have the concept of unsorted edges.
 */
class GrShape {
public:
    // The current set of types GrShape can represent directly
    enum class Type : uint8_t {
        kEmpty, kPoint, kRect, kRRect, kPath, kArc, kLine, kLast = kLine
    };
    static constexpr int kTypeCount = static_cast<int>(Type::kLast) + 1;

    // The direction and start index used when a shape does not have a representable winding,
    // or when that information was discarded during simplification (kIgnoreWinding_Flag).
    static constexpr SkPathDirection kDefaultDir   = SkPathDirection::kCW;
    static constexpr unsigned        kDefaultStart = 0;
    // The fill rule that is used by asPath() for shapes that aren't already a path.
    static constexpr SkPathFillType  kDefaultFillType = SkPathFillType::kEvenOdd;

    GrShape() {}
    explicit GrShape(const SkPoint& point) { this->setPoint(point); }
    explicit GrShape(const SkRect& rect) { this->setRect(rect); }
    explicit GrShape(const SkRRect& rrect) { this->setRRect(rrect); }
    explicit GrShape(const SkPath& path) { this->setPath(path); }
    explicit GrShape(const GrArc& arc) { this->setArc(arc); }
    explicit GrShape(const GrLineSegment& line){ this->setLine(line); }

    explicit GrShape(const GrShape& shape) { *this = shape; }

    ~GrShape() { this->reset(); }

    // NOTE: None of the geometry types benefit from move semantics, so we don't bother
    // defining a move assignment operator for GrShape.
    GrShape& operator=(const GrShape& shape);

    // These type queries reflect the shape type provided when assigned, it does not incorporate
    // any potential simplification (e.g. if isRRect() is true and rrect().isRect() is true,
    // isRect() will still be false, until simplify() is called).
    bool isEmpty() const { return this->type() == Type::kEmpty; }
    bool isPoint() const { return this->type() == Type::kPoint; }
    bool isRect() const { return this->type() == Type::kRect; }
    bool isRRect() const { return this->type() == Type::kRRect; }
    bool isPath() const { return this->type() == Type::kPath; }
    bool isArc() const { return this->type() == Type::kArc; }
    bool isLine() const { return this->type() == Type::kLine; }

    Type type() const { return fType; }

    // Report the shape type, winding direction, start index, and invertedness as a value suitable
    // for use in a resource key. This does not include any geometry coordinates into the key value.
    uint32_t stateKey() const;

    // Whether or not the shape is meant to be the inverse of its geometry (i.e. its exterior).
    bool inverted() const {
        return this->isPath() ? fPath.isInverseFillType() : SkToBool(fInverted);
    }

    // Returns the path direction extracted from the path during simplification, if the shape's
    // type represents a rrect, rect, or oval.
    SkPathDirection dir() const { return fCW ? SkPathDirection::kCW : SkPathDirection::kCCW; }
    // Returns the start index extracted from the path during simplification, if the shape's
    // type represents a rrect, rect, or oval.
    unsigned startIndex() const { return fStart; }

    // Override the direction and start parameters for the simplified contour. These are only
    // meaningful for rects, rrects, and ovals.
    void setPathWindingParams(SkPathDirection dir, unsigned start) {
        SkASSERT((this->isRect() && start < 4) || (this->isRRect() && start < 8) ||
                 (dir == kDefaultDir && start == kDefaultStart));
        fCW = dir == SkPathDirection::kCW;
        fStart = static_cast<uint8_t>(start);
    }

    void setInverted(bool inverted) {
        if (this->isPath()) {
            if (inverted != fPath.isInverseFillType()) {
                fPath.toggleInverseFillType();
            }
        } else {
            fInverted = inverted;
        }
    }

    // Access the actual geometric description of the shape. May only access the appropriate type
    // based on what was last set. The type may change after simplify() is called.
    SkPoint& point() { SkASSERT(this->isPoint()); return fPoint; }
    const SkPoint& point() const { SkASSERT(this->isPoint()); return fPoint; }

    SkRect& rect() { SkASSERT(this->isRect()); return fRect; }
    const SkRect& rect() const { SkASSERT(this->isRect()); return fRect; }

    SkRRect& rrect() { SkASSERT(this->isRRect()); return fRRect; }
    const SkRRect& rrect() const { SkASSERT(this->isRRect()); return fRRect; }

    SkPath& path() { SkASSERT(this->isPath()); return fPath; }
    const SkPath& path() const { SkASSERT(this->isPath()); return fPath; }

    GrArc& arc() { SkASSERT(this->isArc()); return fArc; }
    const GrArc& arc() const { SkASSERT(this->isArc()); return fArc; }

    GrLineSegment& line() { SkASSERT(this->isLine()); return fLine; }
    const GrLineSegment& line() const { SkASSERT(this->isLine()); return fLine; }

    // Update the geometry stored in the GrShape and update its associated type to match. This
    // performs no simplification, so calling setRRect() with a round rect that has isRect() return
    // true will still be considered an rrect by this shape until simplify() is called.
    //
    // These also reset any extracted direction, start, and inverted state from a prior simplified
    // path, since these functions ared used to describe a new geometry.
    void setPoint(const SkPoint& point) {
        this->reset(Type::kPoint);
        fPoint = point;
    }
    void setRect(const SkRect& rect) {
        this->reset(Type::kRect);
        fRect = rect;
    }
    void setRRect(const SkRRect& rrect) {
        this->reset(Type::kRRect);
        fRRect = rrect;
    }
    void setArc(const GrArc& arc) {
        this->reset(Type::kArc);
        fArc = arc;
    }
    void setLine(const GrLineSegment& line) {
        this->reset(Type::kLine);
        fLine = line;
    }
    void setPath(const SkPath& path) {
        if (this->isPath()) {
            // Assign directly
            fPath = path;
        } else {
            // In-place initialize
            this->setType(Type::kPath);
            new (&fPath) SkPath(path);
        }
        // Must also set these since we didn't call reset() like other setX functions.
        this->setPathWindingParams(kDefaultDir, kDefaultStart);
        fInverted = path.isInverseFillType();
    }
    void reset() {
        this->reset(Type::kEmpty);
    }

    // Flags that enable more aggressive, "destructive" simplifications to the geometry
    enum SimplifyFlags : unsigned {
        // If set, it is assumed the original shape would have been implicitly filled when drawn or
        // clipped, so simpler shape types that are closed can still be considered. Shapes with
        // 0 area (i.e. points and lines) can be turned into empty.
        kSimpleFill_Flag    = 0b001,
        // If set, simplifications that would impact a directional stroke or path effect can still
        // be taken (e.g. dir and start are not required, arcs can be converted to ovals).
        kIgnoreWinding_Flag = 0b010,
        // If set, the geometry will be updated to have sorted coordinates (rects, lines), modulated
        // sweep angles (arcs).
        kMakeCanonical_Flag = 0b100,

        kAll_Flags          = 0b111
    };
    // Returns true if the shape was originally closed based on type (or detected type within a
    // path), even if the final simplification results in a point, line, or empty.
    bool simplify(unsigned flags = kAll_Flags);

    // True if the given bounding box is completely inside the shape.
    bool contains(const SkRect& rect) const;

    // True if the underlying geometry represents a closed shape, without the need for an
    // implicit close (note that if simplified earlier with 'simpleFill' = true, a shape that was
    // not closed may become closed).
    bool closed() const;

    // True if the underlying shape is known to be convex, assuming no other styles. If 'simpleFill'
    // is true, it is assumed the contours will be implicitly closed when drawn or used.
    bool convex(bool simpleFill = true) const;

    // The bounding box of the shape.
    SkRect bounds() const;

    // The segment masks that describe the shape, were it to be converted to an SkPath
    uint32_t segmentMask() const;

    // Convert the shape into a path that describes the same geometry.
    void asPath(SkPath* out, bool simpleFill = true) const;

private:

    void setType(Type type) {
        if (this->isPath() && type != Type::kPath) {
            fInverted = fPath.isInverseFillType();
            fPath.~SkPath();
        }
        fType = type;
    }

    void reset(Type type) {
        this->setType(type);
        this->setPathWindingParams(kDefaultDir, kDefaultStart);
        this->setInverted(false);
    }

    // Paths and arcs are root shapes, another type will never simplify to them, so they do
    // not take the geometry to simplify as an argument. Since they are root shapes, they also
    // return whether or not they were originally closed before being simplified.
    bool simplifyPath(unsigned flags);
    bool simplifyArc(unsigned flags);

    // The simpler type classes do take the geometry because it may represent an in-progress
    // simplification that hasn't been set on the GrShape yet. The simpler types do not report
    // whether or not they were closed because it's implicit in their type.
    void simplifyLine(const SkPoint& p1, const SkPoint& p2, unsigned flags);
    void simplifyPoint(const SkPoint& point, unsigned flags);

    // RRects and rects care about winding for path effects and will set the path winding state
    // of the shape as well.
    void simplifyRRect(const SkRRect& rrect, SkPathDirection dir, unsigned start, unsigned flags);
    void simplifyRect(const SkRect& rect, SkPathDirection dir, unsigned start, unsigned flags);

    union {
        SkPoint       fPoint;
        SkRect        fRect;
        SkRRect       fRRect;
        SkPath        fPath;
        GrArc         fArc;
        GrLineSegment fLine;
    };

    Type            fType = Type::kEmpty;
    uint8_t         fStart; // Restricted to rrects and simpler, so this will be < 8
    bool            fCW;
    bool            fInverted;
};

#endif
