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

#ifndef GrQuad_DEFINED
#define GrQuad_DEFINED

#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "include/core/SkPoint3.h"
#include "include/private/SkVx.h"

enum class GrQuadAAFlags;

/**
 * GrQuad is a collection of 4 points which can be used to represent an arbitrary quadrilateral. The
 * points make a triangle strip with CCW triangles (top-left, bottom-left, top-right, bottom-right).
 */
class GrQuad {
public:
    // Quadrilaterals can be classified in several useful ways that assist AA tessellation and other
    // analysis when drawing, in particular, knowing if it was originally a rectangle transformed by
    // certain types of matrices:
    enum class Type {
        // The 4 points remain an axis-aligned rectangle; their logical indices may not respect
        // TL, BL, TR, BR ordering if the transform was a 90 degree rotation or mirror.
        kAxisAligned,
        // The 4 points represent a rectangle subjected to a rotation, its corners are right angles.
        kRectilinear,
        // Arbitrary 2D quadrilateral; may have been a rectangle transformed with skew or some
        // clipped polygon. Its w coordinates will all be 1.
        kGeneral,
        // Even more general-purpose than kGeneral, this allows the w coordinates to be non-unity.
        kPerspective,
        kLast = kPerspective
    };
    static const int kTypeCount = static_cast<int>(Type::kLast) + 1;

    // This enforces W == 1 for non-perspective quads, but does not initialize X or Y.
    GrQuad() = default;
    GrQuad(const GrQuad&) = default;

    explicit GrQuad(const SkRect& rect)
            : fX{rect.fLeft, rect.fLeft, rect.fRight, rect.fRight}
            , fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom} {}

    static GrQuad MakeFromRect(const SkRect&, const SkMatrix&);

    // Creates a GrQuad from the quadrilateral 'pts', transformed by the matrix. The input
    // points array is arranged as per SkRect::toQuad (top-left, top-right, bottom-right,
    // bottom-left). The returned instance's point order will still be CCW tri-strip order.
    static GrQuad MakeFromSkQuad(const SkPoint pts[4], const SkMatrix&);

    GrQuad& operator=(const GrQuad&) = default;

    SkPoint3 point3(int i) const { return {fX[i], fY[i], fW[i]}; }

    SkPoint point(int i) const {
        if (fType == Type::kPerspective) {
            return {fX[i] / fW[i], fY[i] / fW[i]};
        } else {
            return {fX[i], fY[i]};
        }
    }

    SkRect bounds() const {
        if (fType == GrQuad::Type::kPerspective) {
            return this->projectedBounds();
        }
        // Calculate min/max directly on the 4 floats, instead of loading/unloading into SIMD. Since
        // there's no horizontal min/max, it's not worth it. Defining non-perspective case in header
        // also leads to substantial performance boost due to inlining.
        auto min = [](const float c[4]) { return std::min(std::min(c[0], c[1]),
                                                          std::min(c[2], c[3]));};
        auto max = [](const float c[4]) { return std::max(std::max(c[0], c[1]),
                                                          std::max(c[2], c[3]));};
        return { min(fX), min(fY), max(fX), max(fY) };
    }

    bool isFinite() const {
        // If any coordinate is infinity or NaN, then multiplying it with 0 will make accum NaN
        float accum = 0;
        for (int i = 0; i < 4; ++i) {
            accum *= fX[i];
            accum *= fY[i];
            accum *= fW[i];
        }
        SkASSERT(0 == accum || SkScalarIsNaN(accum));
        return !SkScalarIsNaN(accum);
    }

    float x(int i) const { return fX[i]; }
    float y(int i) const { return fY[i]; }
    float w(int i) const { return fW[i]; }
    float iw(int i) const { return sk_ieee_float_divide(1.f, fW[i]); }

    skvx::Vec<4, float> x4f() const { return skvx::Vec<4, float>::Load(fX); }
    skvx::Vec<4, float> y4f() const { return skvx::Vec<4, float>::Load(fY); }
    skvx::Vec<4, float> w4f() const { return skvx::Vec<4, float>::Load(fW); }
    skvx::Vec<4, float> iw4f() const { return 1.f / this->w4f(); }

    Type quadType() const { return fType; }

    bool hasPerspective() const { return fType == Type::kPerspective; }

    // True if anti-aliasing affects this quad. Only valid when quadType == kAxisAligned
    bool aaHasEffectOnRect() const;

    // True if this quad is axis-aligned and still has its top-left corner at v0. Equivalently,
    // quad == GrQuad(quad->bounds()). Axis-aligned quads with flips and rotations may exactly
    // fill their bounds, but their vertex order will not match TL BL TR BR anymore.
    bool asRect(SkRect* rect) const;

    // The non-const pointers are provided to support modifying a GrQuad in-place, but care must be
    // taken to keep its quad type aligned with the geometric nature of the new coordinates.
    const float* xs() const { return fX; }
    float* xs() { return fX; }
    const float* ys() const { return fY; }
    float* ys() { return fY; }
    const float* ws() const { return fW; }
    float* ws() { return fW; }

    // Automatically ensures ws are 1 if new type is not perspective.
    void setQuadType(Type newType) {
        if (newType != Type::kPerspective && fType == Type::kPerspective) {
            fW[0] = fW[1] = fW[2] = fW[3] = 1.f;
        }
        SkASSERT(newType == Type::kPerspective ||
                 (SkScalarNearlyEqual(fW[0], 1.f) && SkScalarNearlyEqual(fW[1], 1.f) &&
                  SkScalarNearlyEqual(fW[2], 1.f) && SkScalarNearlyEqual(fW[3], 1.f)));

        fType = newType;
    }
private:
    template<typename T>
    friend class GrQuadListBase; // for access to fX, fY, fW

    GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys, Type type)
            : fType(type) {
        SkASSERT(type != Type::kPerspective);
        xs.store(fX);
        ys.store(fY);
    }

    GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
           const skvx::Vec<4, float>& ws, Type type)
            : fW{} // Include fW in member initializer to avoid redundant default initializer
            , fType(type) {
        xs.store(fX);
        ys.store(fY);
        ws.store(fW);
    }

    // Defined in GrQuadUtils.cpp to share the coord clipping code
    SkRect projectedBounds() const;

    float fX[4];
    float fY[4];
    float fW[4] = {1.f, 1.f, 1.f, 1.f};

    Type fType = Type::kAxisAligned;
};

// A simple struct representing the common work unit of a pair of device and local coordinates, as
// well as the edge flags controlling anti-aliasing for the quadrilateral when drawn.
struct DrawQuad {
    GrQuad        fDevice;
    GrQuad        fLocal;
    GrQuadAAFlags fEdgeFlags;
};

#endif
