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

#include "GrTypes.h"
#include "SkPathEffect.h"
#include "SkStrokeRec.h"
#include "SkTemplates.h"

/**
 * Represents the various ways that a GrShape can be styled. It has fill/stroking information
 * as well as an optional path effect. If the path effect represents dashing, the dashing
 * information is extracted from the path effect and stored explicitly.
 *
 * This will replace GrStrokeInfo as GrShape is deployed.
 */
class GrStyle {
public:
    /**
     * A style object that represents a fill with no path effect.
     * TODO: constexpr with C++14
     */
    static const GrStyle& SimpleFill() {
        static const GrStyle kFill(SkStrokeRec::kFill_InitStyle);
        return kFill;
        }

    /**
     * A style object that represents a hairline stroke with no path effect.
     * TODO: constexpr with C++14
     */
    static const GrStyle& SimpleHairline() {
        static const GrStyle kHairline(SkStrokeRec::kHairline_InitStyle);
        return kHairline;
    }

    enum class Apply {
        kPathEffectOnly,
        kPathEffectAndStrokeRec
    };

    /**
     * Optional flags for computing keys that may remove unnecessary variation in the key due to
     * style settings that don't affect particular classes of geometry.
     */
    enum KeyFlags {
        // The shape being styled has no open contours.
        kClosed_KeyFlag = 0x1,
        // The shape being styled doesn't have any joins and so isn't affected by join type.
        kNoJoins_KeyFlag = 0x2
    };

    /**
     * Computes the key length for a GrStyle. The return will be negative if it cannot be turned
     * into a key. This occurs when there is a path effect that is not a dash. The key can
     * either reflect just the path effect (if one) or the path effect and the strokerec. Note
     * that a simple fill has a zero sized key.
     */
    static int KeySize(const GrStyle&, Apply, uint32_t flags = 0);

    /**
     * Writes a unique key for the style into the provided buffer. This function assumes the buffer
     * has room for at least KeySize() values. It assumes that KeySize() returns a non-negative
     * value for the combination of GrStyle, Apply and flags params. This is written so that the key
     * for just dash application followed by the key for the remaining SkStrokeRec is the same as
     * the key for applying dashing and SkStrokeRec all at once.
     */
    static void WriteKey(uint32_t*, const GrStyle&, Apply, SkScalar scale, uint32_t flags = 0);

    GrStyle() : GrStyle(SkStrokeRec::kFill_InitStyle) {}

    explicit GrStyle(SkStrokeRec::InitStyle initStyle) : fStrokeRec(initStyle) {}

    GrStyle(const SkStrokeRec& strokeRec, SkPathEffect* pe) : fStrokeRec(strokeRec) {
        this->initPathEffect(pe);
    }

    GrStyle(const GrStyle& that) : fStrokeRec(SkStrokeRec::kFill_InitStyle) { *this = that; }

    explicit GrStyle(const SkPaint& paint) : fStrokeRec(paint) {
        this->initPathEffect(paint.getPathEffect());
    }

    explicit GrStyle(const SkPaint& paint, SkPaint::Style overrideStyle)
            : fStrokeRec(paint, overrideStyle) {
        this->initPathEffect(paint.getPathEffect());
    }

    GrStyle& operator=(const GrStyle& that) {
        fPathEffect = that.fPathEffect;
        fDashInfo = that.fDashInfo;
        fStrokeRec = that.fStrokeRec;
        return *this;
    }

    void resetToInitStyle(SkStrokeRec::InitStyle fillOrHairline) {
        fDashInfo.reset();
        fPathEffect.reset(nullptr);
        if (SkStrokeRec::kFill_InitStyle == fillOrHairline) {
            fStrokeRec.setFillStyle();
        } else {
            fStrokeRec.setHairlineStyle();
        }
    }

    /** Is this style a fill with no path effect? */
    bool isSimpleFill() const { return fStrokeRec.isFillStyle() && !fPathEffect; }

    /** Is this style a hairline with no path effect? */
    bool isSimpleHairline() const { return fStrokeRec.isHairlineStyle() && !fPathEffect; }

    SkPathEffect* pathEffect() const { return fPathEffect.get(); }

    bool hasPathEffect() const { return SkToBool(fPathEffect.get()); }

    bool hasNonDashPathEffect() const { return fPathEffect.get() && !this->isDashed(); }

    bool isDashed() const { return SkPathEffect::kDash_DashType == fDashInfo.fType; }
    SkScalar dashPhase() const {
        SkASSERT(this->isDashed());
        return fDashInfo.fPhase;
    }
    int dashIntervalCnt() const {
        SkASSERT(this->isDashed());
        return fDashInfo.fIntervals.count();
    }
    const SkScalar* dashIntervals() const {
        SkASSERT(this->isDashed());
        return fDashInfo.fIntervals.get();
    }

    const SkStrokeRec& strokeRec() const { return fStrokeRec; }

    /** Hairline or fill styles without path effects make no alterations to a geometry. */
    bool applies() const {
        return this->pathEffect() || (!fStrokeRec.isFillStyle() && !fStrokeRec.isHairlineStyle());
    }

    static SkScalar MatrixToScaleFactor(const SkMatrix& matrix) {
        // getMaxScale will return -1 if the matrix has perspective. In that case we can use a scale
        // factor of 1. This isn't necessarily a good choice and in the future we might consider
        // taking a bounds here for the perspective case.
        return SkScalarAbs(matrix.getMaxScale());
    }
    /**
     * Applies just the path effect and returns remaining stroke information. This will fail if
     * there is no path effect. dst may or may not have been overwritten on failure. Scale controls
     * geometric approximations made by the path effect. It is typically computed from the view
     * matrix.
     */
    bool SK_WARN_UNUSED_RESULT applyPathEffectToPath(SkPath* dst, SkStrokeRec* remainingStoke,
                                                     const SkPath& src, SkScalar scale) const;

    /**
     * If this succeeds then the result path should be filled or hairlined as indicated by the
     * returned SkStrokeRec::InitStyle value. Will fail if there is no path effect and the
     * strokerec doesn't change the geometry. When this fails the outputs may or may not have
     * been overwritten. Scale controls geometric approximations made by the path effect and
     * stroker. It is typically computed from the view matrix.
     */
    bool SK_WARN_UNUSED_RESULT applyToPath(SkPath* dst, SkStrokeRec::InitStyle* fillOrHairline,
                                           const SkPath& src, SkScalar scale) const;

    /** Given bounds of a path compute the bounds of path with the style applied. */
    void adjustBounds(SkRect* dst, const SkRect& src) const {
        if (this->pathEffect()) {
            this->pathEffect()->computeFastBounds(dst, src);
            // This may not be the correct SkStrokeRec to use. skbug.com/5299
            // It happens to work for dashing.
            SkScalar radius = fStrokeRec.getInflationRadius();
            dst->outset(radius, radius);
        } else {
            SkScalar radius = fStrokeRec.getInflationRadius();
            *dst = src.makeOutset(radius, radius);
        }
    }

private:
    void initPathEffect(SkPathEffect* pe);

    struct DashInfo {
        DashInfo() : fType(SkPathEffect::kNone_DashType) {}
        DashInfo& operator=(const DashInfo& that) {
            fType = that.fType;
            fPhase = that.fPhase;
            fIntervals.reset(that.fIntervals.count());
            sk_careful_memcpy(fIntervals.get(), that.fIntervals.get(),
                              sizeof(SkScalar) * that.fIntervals.count());
            return *this;
        }
        void reset() {
            fType = SkPathEffect::kNone_DashType;
            fIntervals.reset(0);
        }
        SkPathEffect::DashType      fType;
        SkScalar                    fPhase;
        SkAutoSTArray<4, SkScalar>  fIntervals;
    };

    bool applyPathEffect(SkPath* dst, SkStrokeRec* strokeRec, const SkPath& src) const;

    SkStrokeRec         fStrokeRec;
    sk_sp<SkPathEffect> fPathEffect;
    DashInfo            fDashInfo;
};

#endif
