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

#ifndef SkRRect_DEFINED
#define SkRRect_DEFINED

#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTypes.h"

#include <cstdint>
#include <cstring>

class SkMatrix;
class SkString;

/** \class SkRRect
    SkRRect describes a rounded rectangle with a bounds and a pair of radii for each corner.
    The bounds and radii can be set so that SkRRect describes: a rectangle with sharp corners;
    a circle; an oval; or a rectangle with one or more rounded corners.

    SkRRect allows implementing CSS properties that describe rounded corners.
    SkRRect may have up to eight different radii, one for each axis on each of its four
    corners.

    SkRRect may modify the provided parameters when initializing bounds and radii.
    If either axis radii is zero or less: radii are stored as zero; corner is square.
    If corner curves overlap, radii are proportionally reduced to fit within bounds.
*/
class SK_API SkRRect {
public:

    /** Initializes bounds at (0, 0), the origin, with zero width and height.
        Initializes corner radii to (0, 0), and sets type of kEmpty_Type.

        @return  empty SkRRect
    */
    SkRRect() = default;

    /** Initializes to copy of rrect bounds and corner radii.

        @param rrect  bounds and corner to copy
        @return       copy of rrect
    */
    SkRRect(const SkRRect& rrect) = default;

    /** Copies rrect bounds and corner radii.

        @param rrect  bounds and corner to copy
        @return       copy of rrect
    */
    SkRRect& operator=(const SkRRect& rrect) = default;

    /** \enum SkRRect::Type
        Type describes possible specializations of SkRRect. Each Type is
        exclusive; a SkRRect may only have one type.

        Type members become progressively less restrictive; larger values of
        Type have more degrees of freedom than smaller values.
    */
    enum Type {
        kEmpty_Type,                     //!< zero width or height
        kRect_Type,                      //!< non-zero width and height, and zeroed radii
        kOval_Type,                      //!< non-zero width and height filled with radii
        kSimple_Type,                    //!< non-zero width and height with equal radii
        kNinePatch_Type,                 //!< non-zero width and height with axis-aligned radii
        kComplex_Type,                   //!< non-zero width and height with arbitrary radii
        kLastType       = kComplex_Type, //!< largest Type value
    };

    Type getType() const {
        SkASSERT(this->isValid());
        return static_cast<Type>(fType);
    }

    Type type() const { return this->getType(); }

    inline bool isEmpty() const { return kEmpty_Type == this->getType(); }
    inline bool isRect() const { return kRect_Type == this->getType(); }
    inline bool isOval() const { return kOval_Type == this->getType(); }
    inline bool isSimple() const { return kSimple_Type == this->getType(); }
    inline bool isNinePatch() const { return kNinePatch_Type == this->getType(); }
    inline bool isComplex() const { return kComplex_Type == this->getType(); }

    /** Returns span on the x-axis. This does not check if result fits in 32-bit float;
        result may be infinity.

        @return  rect().fRight minus rect().fLeft
    */
    SkScalar width() const { return fRect.width(); }

    /** Returns span on the y-axis. This does not check if result fits in 32-bit float;
        result may be infinity.

        @return  rect().fBottom minus rect().fTop
    */
    SkScalar height() const { return fRect.height(); }

    /** Returns top-left corner radii. If type() returns kEmpty_Type, kRect_Type,
        kOval_Type, or kSimple_Type, returns a value representative of all corner radii.
        If type() returns kNinePatch_Type or kComplex_Type, at least one of the
        remaining three corners has a different value.

        @return  corner radii for simple types
    */
    SkVector getSimpleRadii() const {
        return fRadii[0];
    }

    /** Sets bounds to zero width and height at (0, 0), the origin. Sets
        corner radii to zero and sets type to kEmpty_Type.
    */
    void setEmpty() { *this = SkRRect(); }

    /** Sets bounds to sorted rect, and sets corner radii to zero.
        If set bounds has width and height, and sets type to kRect_Type;
        otherwise, sets type to kEmpty_Type.

        @param rect  bounds to set
    */
    void setRect(const SkRect& rect) {
        if (!this->initializeRect(rect)) {
            return;
        }

        memset(fRadii, 0, sizeof(fRadii));
        fType = kRect_Type;

        SkASSERT(this->isValid());
    }

    /** Initializes bounds at (0, 0), the origin, with zero width and height.
        Initializes corner radii to (0, 0), and sets type of kEmpty_Type.

        @return  empty SkRRect
    */
    static SkRRect MakeEmpty() { return SkRRect(); }

    /** Initializes to copy of r bounds and zeroes corner radii.

        @param r  bounds to copy
        @return   copy of r
    */
    static SkRRect MakeRect(const SkRect& r) {
        SkRRect rr;
        rr.setRect(r);
        return rr;
    }

    /** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii
        to half oval.height(). If oval bounds is empty, sets to kEmpty_Type.
        Otherwise, sets to kOval_Type.

        @param oval  bounds of oval
        @return      oval
    */
    static SkRRect MakeOval(const SkRect& oval) {
        SkRRect rr;
        rr.setOval(oval);
        return rr;
    }

    /** Sets to rounded rectangle with the same radii for all four corners.
        If rect is empty, sets to kEmpty_Type.
        Otherwise, if xRad and yRad are zero, sets to kRect_Type.
        Otherwise, if xRad is at least half rect.width() and yRad is at least half
        rect.height(), sets to kOval_Type.
        Otherwise, sets to kSimple_Type.

        @param rect  bounds of rounded rectangle
        @param xRad  x-axis radius of corners
        @param yRad  y-axis radius of corners
        @return      rounded rectangle
    */
    static SkRRect MakeRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad) {
        SkRRect rr;
        rr.setRectXY(rect, xRad, yRad);
        return rr;
    }

    /** Sets bounds to oval, x-axis radii to half oval.width(), and all y-axis radii
        to half oval.height(). If oval bounds is empty, sets to kEmpty_Type.
        Otherwise, sets to kOval_Type.

        @param oval  bounds of oval
    */
    void setOval(const SkRect& oval);

    /** Sets to rounded rectangle with the same radii for all four corners.
        If rect is empty, sets to kEmpty_Type.
        Otherwise, if xRad or yRad is zero, sets to kRect_Type.
        Otherwise, if xRad is at least half rect.width() and yRad is at least half
        rect.height(), sets to kOval_Type.
        Otherwise, sets to kSimple_Type.

        @param rect  bounds of rounded rectangle
        @param xRad  x-axis radius of corners
        @param yRad  y-axis radius of corners

        example: https://fiddle.skia.org/c/@RRect_setRectXY
    */
    void setRectXY(const SkRect& rect, SkScalar xRad, SkScalar yRad);

    /** Sets bounds to rect. Sets radii to (leftRad, topRad), (rightRad, topRad),
        (rightRad, bottomRad), (leftRad, bottomRad).

        If rect is empty, sets to kEmpty_Type.
        Otherwise, if leftRad and rightRad are zero, sets to kRect_Type.
        Otherwise, if topRad and bottomRad are zero, sets to kRect_Type.
        Otherwise, if leftRad and rightRad are equal and at least half rect.width(), and
        topRad and bottomRad are equal at least half rect.height(), sets to kOval_Type.
        Otherwise, if leftRad and rightRad are equal, and topRad and bottomRad are equal,
        sets to kSimple_Type. Otherwise, sets to kNinePatch_Type.

        Nine patch refers to the nine parts defined by the radii: one center rectangle,
        four edge patches, and four corner patches.

        @param rect       bounds of rounded rectangle
        @param leftRad    left-top and left-bottom x-axis radius
        @param topRad     left-top and right-top y-axis radius
        @param rightRad   right-top and right-bottom x-axis radius
        @param bottomRad  left-bottom and right-bottom y-axis radius
    */
    void setNinePatch(const SkRect& rect, SkScalar leftRad, SkScalar topRad,
                      SkScalar rightRad, SkScalar bottomRad);

    /** Sets bounds to rect. Sets radii array for individual control of all for corners.

        If rect is empty, sets to kEmpty_Type.
        Otherwise, if one of each corner radii are zero, sets to kRect_Type.
        Otherwise, if all x-axis radii are equal and at least half rect.width(), and
        all y-axis radii are equal at least half rect.height(), sets to kOval_Type.
        Otherwise, if all x-axis radii are equal, and all y-axis radii are equal,
        sets to kSimple_Type. Otherwise, sets to kNinePatch_Type.

        @param rect   bounds of rounded rectangle
        @param radii  corner x-axis and y-axis radii

        example: https://fiddle.skia.org/c/@RRect_setRectRadii
    */
    void setRectRadii(const SkRect& rect, const SkVector radii[4]);

    /** \enum SkRRect::Corner
        The radii are stored: top-left, top-right, bottom-right, bottom-left.
    */
    enum Corner {
        kUpperLeft_Corner,  //!< index of top-left corner radii
        kUpperRight_Corner, //!< index of top-right corner radii
        kLowerRight_Corner, //!< index of bottom-right corner radii
        kLowerLeft_Corner,  //!< index of bottom-left corner radii
    };

    /** Returns bounds. Bounds may have zero width or zero height. Bounds right is
        greater than or equal to left; bounds bottom is greater than or equal to top.
        Result is identical to getBounds().

        @return  bounding box
    */
    const SkRect& rect() const { return fRect; }

    /** Returns scalar pair for radius of curve on x-axis and y-axis for one corner.
        Both radii may be zero. If not zero, both are positive and finite.

        @return        x-axis and y-axis radii for one corner
    */
    SkVector radii(Corner corner) const { return fRadii[corner]; }

    /** Returns bounds. Bounds may have zero width or zero height. Bounds right is
        greater than or equal to left; bounds bottom is greater than or equal to top.
        Result is identical to rect().

        @return  bounding box
    */
    const SkRect& getBounds() const { return fRect; }

    /** Returns true if bounds and radii in a are equal to bounds and radii in b.

        a and b are not equal if either contain NaN. a and b are equal if members
        contain zeroes with different signs.

        @param a  SkRect bounds and radii to compare
        @param b  SkRect bounds and radii to compare
        @return   true if members are equal
    */
    friend bool operator==(const SkRRect& a, const SkRRect& b) {
        return a.fRect == b.fRect && SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);
    }

    /** Returns true if bounds and radii in a are not equal to bounds and radii in b.

        a and b are not equal if either contain NaN. a and b are equal if members
        contain zeroes with different signs.

        @param a  SkRect bounds and radii to compare
        @param b  SkRect bounds and radii to compare
        @return   true if members are not equal
    */
    friend bool operator!=(const SkRRect& a, const SkRRect& b) {
        return a.fRect != b.fRect || !SkScalarsEqual(&a.fRadii[0].fX, &b.fRadii[0].fX, 8);
    }

    /** Copies SkRRect to dst, then insets dst bounds by dx and dy, and adjusts dst
        radii by dx and dy. dx and dy may be positive, negative, or zero. dst may be
        SkRRect.

        If either corner radius is zero, the corner has no curvature and is unchanged.
        Otherwise, if adjusted radius becomes negative, pins radius to zero.
        If dx exceeds half dst bounds width, dst bounds left and right are set to
        bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and
        bottom are set to bounds y-axis center.

        If dx or dy cause the bounds to become infinite, dst bounds is zeroed.

        @param dx   added to rect().fLeft, and subtracted from rect().fRight
        @param dy   added to rect().fTop, and subtracted from rect().fBottom
        @param dst  insets bounds and radii

        example: https://fiddle.skia.org/c/@RRect_inset
    */
    void inset(SkScalar dx, SkScalar dy, SkRRect* dst) const;

    /** Insets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
        positive, negative, or zero.

        If either corner radius is zero, the corner has no curvature and is unchanged.
        Otherwise, if adjusted radius becomes negative, pins radius to zero.
        If dx exceeds half bounds width, bounds left and right are set to
        bounds x-axis center. If dy exceeds half bounds height, bounds top and
        bottom are set to bounds y-axis center.

        If dx or dy cause the bounds to become infinite, bounds is zeroed.

        @param dx  added to rect().fLeft, and subtracted from rect().fRight
        @param dy  added to rect().fTop, and subtracted from rect().fBottom
    */
    void inset(SkScalar dx, SkScalar dy) {
        this->inset(dx, dy, this);
    }

    /** Outsets dst bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
        positive, negative, or zero.

        If either corner radius is zero, the corner has no curvature and is unchanged.
        Otherwise, if adjusted radius becomes negative, pins radius to zero.
        If dx exceeds half dst bounds width, dst bounds left and right are set to
        bounds x-axis center. If dy exceeds half dst bounds height, dst bounds top and
        bottom are set to bounds y-axis center.

        If dx or dy cause the bounds to become infinite, dst bounds is zeroed.

        @param dx   subtracted from rect().fLeft, and added to rect().fRight
        @param dy   subtracted from rect().fTop, and added to rect().fBottom
        @param dst  outset bounds and radii
    */
    void outset(SkScalar dx, SkScalar dy, SkRRect* dst) const {
        this->inset(-dx, -dy, dst);
    }

    /** Outsets bounds by dx and dy, and adjusts radii by dx and dy. dx and dy may be
        positive, negative, or zero.

        If either corner radius is zero, the corner has no curvature and is unchanged.
        Otherwise, if adjusted radius becomes negative, pins radius to zero.
        If dx exceeds half bounds width, bounds left and right are set to
        bounds x-axis center. If dy exceeds half bounds height, bounds top and
        bottom are set to bounds y-axis center.

        If dx or dy cause the bounds to become infinite, bounds is zeroed.

        @param dx  subtracted from rect().fLeft, and added to rect().fRight
        @param dy  subtracted from rect().fTop, and added to rect().fBottom
    */
    void outset(SkScalar dx, SkScalar dy) {
        this->inset(-dx, -dy, this);
    }

    /** Translates SkRRect by (dx, dy).

        @param dx  offset added to rect().fLeft and rect().fRight
        @param dy  offset added to rect().fTop and rect().fBottom
    */
    void offset(SkScalar dx, SkScalar dy) {
        fRect.offset(dx, dy);
    }

    /** Returns SkRRect translated by (dx, dy).

        @param dx  offset added to rect().fLeft and rect().fRight
        @param dy  offset added to rect().fTop and rect().fBottom
        @return    SkRRect bounds offset by (dx, dy), with unchanged corner radii
    */
    SkRRect SK_WARN_UNUSED_RESULT makeOffset(SkScalar dx, SkScalar dy) const {
        return SkRRect(fRect.makeOffset(dx, dy), fRadii, fType);
    }

    /** Returns true if rect is inside the bounds and corner radii, and if
        SkRRect and rect are not empty.

        @param rect  area tested for containment
        @return      true if SkRRect contains rect

        example: https://fiddle.skia.org/c/@RRect_contains
    */
    bool contains(const SkRect& rect) const;

    /** Returns true if bounds and radii values are finite and describe a SkRRect
        SkRRect::Type that matches getType(). All SkRRect methods construct valid types,
        even if the input values are not valid. Invalid SkRRect data can only
        be generated by corrupting memory.

        @return  true if bounds and radii match type()

        example: https://fiddle.skia.org/c/@RRect_isValid
    */
    bool isValid() const;

    static constexpr size_t kSizeInMemory = 12 * sizeof(SkScalar);

    /** Writes SkRRect to buffer. Writes kSizeInMemory bytes, and returns
        kSizeInMemory, the number of bytes written.

        @param buffer  storage for SkRRect
        @return        bytes written, kSizeInMemory

        example: https://fiddle.skia.org/c/@RRect_writeToMemory
    */
    size_t writeToMemory(void* buffer) const;

    /** Reads SkRRect from buffer, reading kSizeInMemory bytes.
        Returns kSizeInMemory, bytes read if length is at least kSizeInMemory.
        Otherwise, returns zero.

        @param buffer  memory to read from
        @param length  size of buffer
        @return        bytes read, or 0 if length is less than kSizeInMemory

        example: https://fiddle.skia.org/c/@RRect_readFromMemory
    */
    size_t readFromMemory(const void* buffer, size_t length);

    /** Transforms by SkRRect by matrix, storing result in dst.
        Returns true if SkRRect transformed can be represented by another SkRRect.
        Returns false if matrix contains transformations that are not axis aligned.

        Asserts in debug builds if SkRRect equals dst.

        @param matrix  SkMatrix specifying the transform
        @param dst     SkRRect to store the result
        @return        true if transformation succeeded.

        example: https://fiddle.skia.org/c/@RRect_transform
    */
    bool transform(const SkMatrix& matrix, SkRRect* dst) const;

    /** Writes text representation of SkRRect to standard output.
        Set asHex true to generate exact binary representations
        of floating point numbers.

        @param asHex  true if SkScalar values are written as hexadecimal

        example: https://fiddle.skia.org/c/@RRect_dump
    */
    void dump(bool asHex) const;
    SkString dumpToString(bool asHex) const;

    /** Writes text representation of SkRRect to standard output. The representation
        may be directly compiled as C++ code. Floating point values are written
        with limited precision; it may not be possible to reconstruct original
        SkRRect from output.
    */
    void dump() const { this->dump(false); }

    /** Writes text representation of SkRRect to standard output. The representation
        may be directly compiled as C++ code. Floating point values are written
        in hexadecimal to preserve their exact bit pattern. The output reconstructs the
        original SkRRect.
    */
    void dumpHex() const { this->dump(true); }

private:
    static bool AreRectAndRadiiValid(const SkRect&, const SkVector[4]);

    SkRRect(const SkRect& rect, const SkVector radii[4], int32_t type)
        : fRect(rect)
        , fRadii{radii[0], radii[1], radii[2], radii[3]}
        , fType(type) {}

    /**
     * Initializes fRect. If the passed in rect is not finite or empty the rrect will be fully
     * initialized and false is returned. Otherwise, just fRect is initialized and true is returned.
     */
    bool initializeRect(const SkRect&);

    void computeType();
    bool checkCornerContainment(SkScalar x, SkScalar y) const;
    // Returns true if the radii had to be scaled to fit rect
    bool scaleRadii();

    SkRect fRect = SkRect::MakeEmpty();
    // Radii order is UL, UR, LR, LL. Use Corner enum to index into fRadii[]
    SkVector fRadii[4] = {{0, 0}, {0, 0}, {0,0}, {0,0}};
    // use an explicitly sized type so we're sure the class is dense (no uninitialized bytes)
    int32_t fType = kEmpty_Type;
    // TODO: add padding so we can use memcpy for flattening and not copy uninitialized data

    // to access fRadii directly
    friend class SkPath;
    friend class SkRRectPriv;
};

#endif
