/*
 * 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 GrStyledShape_DEFINED
#define GrStyledShape_DEFINED

#include "include/core/SkPath.h"
#include "include/core/SkRRect.h"
#include "include/private/SkTemplates.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkTLazy.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/geometry/GrShape.h"
#include <new>

class SkIDChangeListener;

/**
 * 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 GrStyledShape to produce a new GrStyledShape 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 fast paths in the GPU backend.
 */
class GrStyledShape {
public:
    // Keys for paths may be extracted from the path data for small paths. Clients aren't supposed
    // to have to worry about this. This value is exposed for unit tests.
    inline static constexpr int kMaxKeyFromDataVerbCnt = 10;

    GrStyledShape() {}

    enum class DoSimplify : bool { kNo = false, kYes };

    explicit GrStyledShape(const SkPath& path, DoSimplify doSimplify = DoSimplify::kYes)
            : GrStyledShape(path, GrStyle::SimpleFill(), doSimplify) {}

    explicit GrStyledShape(const SkRRect& rrect, DoSimplify doSimplify = DoSimplify::kYes)
            : GrStyledShape(rrect, GrStyle::SimpleFill(), doSimplify) {}

    explicit GrStyledShape(const SkRect& rect, DoSimplify doSimplify = DoSimplify::kYes)
            : GrStyledShape(rect, GrStyle::SimpleFill(), doSimplify) {}

    GrStyledShape(const SkPath& path, const SkPaint& paint,
                  DoSimplify doSimplify = DoSimplify::kYes)
            : GrStyledShape(path, GrStyle(paint), doSimplify) {}

    GrStyledShape(const SkRRect& rrect, const SkPaint& paint,
                  DoSimplify doSimplify = DoSimplify::kYes)
            : GrStyledShape(rrect, GrStyle(paint), doSimplify) {}

    GrStyledShape(const SkRect& rect, const SkPaint& paint,
                  DoSimplify doSimplify = DoSimplify::kYes)
            : GrStyledShape(rect, GrStyle(paint), doSimplify) {}

    GrStyledShape(const SkPath& path, const GrStyle& style,
                  DoSimplify doSimplify = DoSimplify::kYes)
            : fShape(path), fStyle(style) {
        if (doSimplify == DoSimplify::kYes) {
            this->simplify();
        }
    }

    GrStyledShape(const SkRRect& rrect, const GrStyle& style,
                  DoSimplify doSimplify = DoSimplify::kYes)
            : fShape(rrect), fStyle(style) {
        if (doSimplify == DoSimplify::kYes) {
            this->simplify();
        }
    }

    GrStyledShape(const SkRRect& rrect, SkPathDirection dir, unsigned start, bool inverted,
                  const GrStyle& style, DoSimplify doSimplify = DoSimplify::kYes)
            : fShape(rrect)
            , fStyle(style) {
        fShape.setPathWindingParams(dir, start);
        fShape.setInverted(inverted);
        if (doSimplify == DoSimplify::kYes) {
            this->simplify();
        }
    }

    GrStyledShape(const SkRect& rect, const GrStyle& style,
                  DoSimplify doSimplify = DoSimplify::kYes)
            : fShape(rect), fStyle(style) {
        if (doSimplify == DoSimplify::kYes) {
            this->simplify();
        }
    }

    GrStyledShape(const GrStyledShape&);

    static GrStyledShape MakeArc(const SkRect& oval, SkScalar startAngleDegrees,
                                 SkScalar sweepAngleDegrees, bool useCenter, const GrStyle& style,
                                 DoSimplify = DoSimplify::kYes);

    GrStyledShape& operator=(const GrStyledShape& that);

    /**
     * Informs MakeFilled on how to modify that shape's fill rule when making a simple filled
     * version of the shape.
     */
    enum class FillInversion {
        kPreserve,
        kFlip,
        kForceNoninverted,
        kForceInverted
    };
    /**
     * Makes a filled shape from the pre-styled original shape and optionally modifies whether
     * the fill is inverted or not. It's important to note that the original shape's geometry
     * may already have been modified if doing so was neutral with respect to its style
     * (e.g. filled paths are always closed when stored in a shape and dashed paths are always
     * made non-inverted since dashing ignores inverseness).
     */
    static GrStyledShape MakeFilled(const GrStyledShape& original,
                                    FillInversion = FillInversion::kPreserve);

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

    // True if the shape and/or style were modified into a simpler, equivalent pairing
    bool simplified() const { return fSimplified; }

    /**
     * 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
     */
    GrStyledShape applyStyle(GrStyle::Apply apply, SkScalar scale) const {
        return GrStyledShape(*this, apply, scale);
    }

    bool isRect() const {
        // Should have simplified a rrect to a rect if possible already.
        SkASSERT(!fShape.isRRect() || !fShape.rrect().isRect());
        return fShape.isRect();
    }

    /** Returns the unstyled geometry as a rrect if possible. */
    bool asRRect(SkRRect* rrect, SkPathDirection* dir, unsigned* start, bool* inverted) const;

    /**
     * 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], bool* inverted) const;

    // Can this shape be drawn as a pair of filled nested rectangles?
    bool asNestedRects(SkRect rects[2]) const;

    /** Returns the unstyled geometry as a path. */
    void asPath(SkPath* out) const {
        fShape.asPath(out, fStyle.isSimpleFill());
    }

    /**
     * Returns whether the geometry is empty. Note that applying the style could produce a
     * non-empty shape. It also may have an inverse fill.
     */
    bool isEmpty() const { return fShape.isEmpty(); }

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

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

    /**
     * Is this shape known to be convex, before styling is applied. An unclosed but otherwise
     * convex path is considered to be closed if they styling reflects a fill and not otherwise.
     * This is because filling closes all contours in the path.
     */
    bool knownToBeConvex() const {
        return fShape.convex(fStyle.isSimpleFill());
    }

    /**
     * Does the shape have a known winding direction. Some degenerate convex shapes may not have
     * a computable direction, but this is not always a requirement for path renderers so it is
     * kept separate from knownToBeConvex().
     */
    bool knownDirection() const {
        // Assuming this is called after knownToBeConvex(), this should just be relying on
        // cached convexity and direction and will be cheap.
        return !fShape.isPath() ||
               SkPathPriv::ComputeFirstDirection(fShape.path()) != SkPathFirstDirection::kUnknown;
    }

    /** Is the pre-styled geometry inverse filled? */
    bool inverseFilled() const {
        // Since the path tracks inverted-fillness itself, it should match what was recorded.
        SkASSERT(!fShape.isPath() || fShape.inverted() == fShape.path().isInverseFillType());
        // Dashing ignores inverseness. We should have caught this earlier. skbug.com/5421
        SkASSERT(!(fShape.inverted() && this->style().isDashed()));
        return fShape.inverted();
    }

    /**
     * Might applying the styling to the geometry produce an inverse fill. The "may" part comes in
     * because an arbitrary path effect could produce an inverse filled path. In other cases this
     * can be thought of as "inverseFilledAfterStyling()".
     */
    bool mayBeInverseFilledAfterStyling() const {
         // An arbitrary path effect can produce an arbitrary output path, which may be inverse
         // filled.
        if (this->style().hasNonDashPathEffect()) {
            return true;
        }
        return this->inverseFilled();
    }

    /**
     * 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 {
        // This refers to the base shape and does not depend on invertedness.
        return fShape.closed();
    }

    uint32_t segmentMask() const {
        // This refers to the base shape and does not depend on invertedness.
        return fShape.segmentMask();
    }

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

    bool hasUnstyledKey() const { return this->unstyledKeySize() >= 0; }

    /**
     * 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;

    /**
     * Adds a listener to the *original* path. Typically used to invalidate cached resources when
     * a path is no longer in-use. If the shape started out as something other than a path, this
     * does nothing.
     */
    void addGenIDChangeListener(sk_sp<SkIDChangeListener>) const;

    /**
     * Helpers that are only exposed for unit tests, to determine if the shape is a path, and get
     * the generation ID of the *original* path. This is the path that will receive
     * GenIDChangeListeners added to this shape.
     */
    uint32_t testingOnly_getOriginalGenerationID() const;
    bool testingOnly_isPath() const;
    bool testingOnly_isNonVolatilePath() const;

    /**
     * Similar to GrShape::simplify but also takes into account style and stroking, possibly
     * applying the style explicitly to produce a new analytic shape with a simpler style.
     * Unless "doSimplify" is kNo, this method gets called automatically during construction.
     */
    void simplify();

private:
    /** Constructor used by the applyStyle() function */
    GrStyledShape(const GrStyledShape& 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 GrStyledShape& parentShape, GrStyle::Apply, SkScalar scale);

    /**
     * As part of the simplification process, some shapes can have stroking trivially evaluated
     * and form a new geometry with just a fill.
     */
    void simplifyStroke();

    /** Gets the path that gen id listeners should be added to. */
    const SkPath* originalPathForListeners() const;

    GrShape fShape;
    GrStyle fStyle;
    // Gen ID of the original path (path may be modified or simplified away).
    int32_t fGenID      = 0;
    bool    fClosed     = false;
    bool    fSimplified = false;

    SkTLazy<SkPath>            fInheritedPathForListeners;
    SkAutoSTArray<8, uint32_t> fInheritedKey;
};
#endif
