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