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

#ifndef skgpu_graphite_geom_Rect_DEFINED
#define skgpu_graphite_geom_Rect_DEFINED

#include "include/core/SkRect.h"
#include "src/base/SkVx.h"

namespace skgpu::graphite {

#define AI SK_ALWAYS_INLINE

/**
 * SIMD rect implementation. Values are stored internally in the form: [left, top, -right, -bot].
 *
 * Some operations (e.g., intersect, inset) may return a negative or empty rect
 * (negative meaning, left >= right or top >= bot).
 *
 * Operations on a rect that is either negative or empty, while well-defined, might not give the
 * intended result. It is the caller's responsibility to check isEmptyOrNegative() if needed.
 */
class Rect {
    using float2 = skvx::float2;
    using float4 = skvx::float4;
public:
    AI Rect() = default;
    AI Rect(float l, float t, float r, float b) : fVals(NegateBotRight({l,t,r,b})) {}
    AI Rect(float2 topLeft, float2 botRight) : fVals(topLeft, -botRight) {}
    AI Rect(const SkRect& r) : fVals(NegateBotRight(float4::Load(r.asScalars()))) {}

    AI static Rect LTRB(float4 ltrb) {
        return Rect(NegateBotRight(ltrb));
    }

    AI static Rect XYWH(float x, float y, float w, float h) {
        return Rect(x, y, x + w, y + h);
    }
    AI static Rect XYWH(float2 topLeft, float2 size) {
        return Rect(topLeft, topLeft + size);
    }
    AI static Rect WH(float w, float h) {
        return Rect(0, 0, w, h);
    }
    AI static Rect WH(float2 size) {
        return Rect(float2(0), size);
    }
    AI static Rect Point(float2 p) {
        return Rect(p, p);
    }
    AI static Rect FromVals(float4 vals) {  // vals.zw must already be negated.
        return Rect(vals);
    }

    // Constructs a Rect with ltrb = [-inf, -inf, inf, inf], useful for accumulating intersections
    AI static Rect Infinite() {
        return FromVals(float4(SK_FloatNegativeInfinity));
    }
    // Constructs a negative Rect with ltrb = [inf, inf, -inf, -inf], useful for accumulating unions
    AI static Rect InfiniteInverted() {
        return FromVals(float4(SK_FloatInfinity));
    }

    AI bool operator==(Rect rect) const { return all(fVals == rect.fVals); }
    AI bool operator!=(Rect rect) const { return any(fVals != rect.fVals); }

    AI const float4& vals() const { return fVals; }  // [left, top, -right, -bot].
    AI float4& vals() { return fVals; }  // [left, top, -right, -bot].

    AI float x() const { return fVals.x(); }
    AI float y() const { return fVals.y(); }
    AI float left() const { return fVals.x(); }
    AI float top() const { return fVals.y(); }
    AI float right() const { return -fVals.z(); }
    AI float bot() const { return -fVals.w(); }
    AI float2 topLeft() const { return fVals.xy(); }
    AI float2 botRight() const { return -fVals.zw(); }
    AI float4 ltrb() const { return NegateBotRight(fVals); }

    AI void setLeft(float left) { fVals.x() = left; }
    AI void setTop(float top) { fVals.y() = top; }
    AI void setRight(float right) { fVals.z() = -right; }
    AI void setBot(float bot) { fVals.w() = -bot; }
    AI void setTopLeft(float2 topLeft) { fVals.xy() = topLeft; }
    AI void setBotRight(float2 botRight) { fVals.zw() = -botRight; }

    AI SkRect asSkRect() const {
        SkRect rect;
        this->ltrb().store(&rect);
        return rect;
    }
    AI SkIRect asSkIRect() const {
        SkIRect rect;
        skvx::cast<int>(this->ltrb()).store(&rect);
        return rect;
    }

    AI bool isEmptyNegativeOrNaN() const {
        return !all(fVals.xy() + fVals.zw() < 0);  // !([l-r, r-b] < 0) == ([w, h] <= 0)
                                                   // Use "!(-size < 0)" in order to detect NaN.
    }

    AI float2 size() const { return -(fVals.xy() + fVals.zw()); }  // == [-(l-r), -(t-b)] == [w, h]

    AI float2 center() const {
        float4 p = fVals * float4(.5f, .5f, -.5f, -.5f);  // == [l, t, r, b] * .5
        return p.xy() + p.zw();  // == [(l + r)/2, (t + b)/2]
    }

    AI float area() const {
        float2 negativeSize = fVals.xy() + fVals.zw();  // == [l-r, t-b] == [-w, -h]
        return negativeSize.x() * negativeSize.y();
    }

    // A rect stored in a complementary form of: [right, bottom, -left, -top]. Store a local
    // ComplementRect object if intersects() will be called many times.
    struct ComplementRect {
        AI ComplementRect(Rect rect) : fVals(-rect.fVals.zwxy()) {}
        float4 fVals;  // [right, bottom, -left, -top]
    };

    AI bool intersects(ComplementRect comp) const { return all(fVals < comp.fVals); }
    AI bool contains(Rect rect) const { return all(fVals <= rect.fVals); }

    // Some operations may return a negative or empty rect. Operations on a rect that either is
    // negative or empty, while well-defined, might not give the intended result. It is the caller's
    // responsibility to check isEmptyOrNegative() if needed.
    AI Rect makeRoundIn() const { return ceil(fVals); }
    AI Rect makeRoundOut() const { return floor(fVals); }
    AI Rect makeInset(float inset) const { return fVals + inset; }
    AI Rect makeInset(float2 inset) const { return fVals + inset.xyxy(); }
    AI Rect makeOutset(float outset) const { return fVals - outset; }
    AI Rect makeOutset(float2 outset) const { return fVals - outset.xyxy(); }
    AI Rect makeOffset(float2 offset) const { return fVals + float4(offset, -offset); }
    AI Rect makeJoin(Rect rect) const { return min(fVals, rect.fVals); }
    AI Rect makeIntersect(Rect rect) const { return max(fVals, rect.fVals); }
    AI Rect makeSorted() const { return min(fVals, -fVals.zwxy()); }

    AI Rect& roundIn() { return *this = this->makeRoundIn(); }
    AI Rect& roundOut() { return *this = this->makeRoundOut(); }
    AI Rect& inset(float inset) { return *this = this->makeInset(inset); }
    AI Rect& inset(float2 inset) { return *this = this->makeInset(inset); }
    AI Rect& outset(float outset) { return *this = this->makeOutset(outset); }
    AI Rect& outset(float2 outset) { return *this = this->makeOutset(outset); }
    AI Rect& offset(float2 offset) { return *this = this->makeOffset(offset); }
    AI Rect& join(Rect rect) { return *this = this->makeJoin(rect); }
    AI Rect& intersect(Rect rect) { return *this = this->makeIntersect(rect); }
    AI Rect& sort() { return *this = this->makeSorted(); }

private:
    AI static float4 NegateBotRight(float4 vals) {  // Returns [vals.xy, -vals.zw].
        using uint4 = skvx::uint4;
        return sk_bit_cast<float4>(sk_bit_cast<uint4>(vals) ^ uint4(0, 0, 1u << 31, 1u << 31));
    }

    AI Rect(float4 vals) : fVals(vals) {}  // vals.zw must already be negated.

    float4 fVals;  // [left, top, -right, -bottom]
};

#undef AI

} // namespace skgpu::graphite

#endif // skgpu_graphite_geom_Rect_DEFINED
