/*
 * 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"
#include "src/gpu/BufferWriter.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]};
        }
    }

    void writeVertex(int cornerIdx, skgpu::VertexWriter& w) const {
        w << this->point(cornerIdx);
    }

    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(GrQuadAAFlags edgeFlags) 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;
};

template<> struct skgpu::VertexWriter::is_quad<GrQuad> : std::true_type {};

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