/*
 * Copyright 2005 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkRegion_DEFINED
#define SkRegion_DEFINED

#include "SkRect.h"

class SkPath;
class SkRgnBuilder;

/** \class SkRegion
    SkRegion describes the set of pixels used to clip SkCanvas. SkRegion is compact,
    efficiently storing a single integer rectangle, or a run length encoded array
    of rectangles. SkRegion may reduce the current SkCanvas clip, or may be drawn as
    one or more integer rectangles. SkRegion iterator returns the scan lines or
    rectangles contained by it, optionally intersecting a bounding rectangle.
*/
class SK_API SkRegion {
    typedef int32_t RunType;
public:

    /** Constructs an empty SkRegion. SkRegion is set to empty bounds
        at (0, 0) with zero width and height.

        @return  empty SkRegion
    */
    SkRegion();

    /** Constructs a copy of an existing region.
        Copy constructor makes two regions identical by value. Internally, region and
        the returned result share pointer values. The underlying SkRect array is
        copied when modified.

        Creating a SkRegion copy is very efficient and never allocates memory.
        SkRegion are always copied by value from the interface; the underlying shared
        pointers are not exposed.

        @param region  SkRegion to copy by value
        @return        copy of SkRegion
    */
    SkRegion(const SkRegion& region);

    /** Constructs a rectangular SkRegion matching the bounds of rect.

        @param rect  bounds of constructed SkRegion
        @return      rectangular SkRegion
    */
    explicit SkRegion(const SkIRect& rect);

    /** Releases ownership of any shared data and deletes data if SkRegion is sole owner.
    */
    ~SkRegion();

    /** Constructs a copy of an existing region.
        Makes two regions identical by value. Internally, region and
        the returned result share pointer values. The underlying SkRect array is
        copied when modified.

        Creating a SkRegion copy is very efficient and never allocates memory.
        SkRegion are always copied by value from the interface; the underlying shared
        pointers are not exposed.

        @param region  SkRegion to copy by value
        @return        SkRegion to copy by value
    */
    SkRegion& operator=(const SkRegion& region);

    /** Compares SkRegion and other; returns true if they enclose exactly
        the same area.

        @param other  SkRegion to compare
        @return       true if SkRegion pair are equivalent
    */
    bool operator==(const SkRegion& other) const;

    /** Compares SkRegion and other; returns true if they do not enclose the same area.

        @param other  SkRegion to compare
        @return       true if SkRegion pair are not equivalent
    */
    bool operator!=(const SkRegion& other) const {
        return !(*this == other);
    }

    /** Sets SkRegion to src, and returns true if src bounds is not empty.
        This makes SkRegion and src identical by value. Internally,
        SkRegion and src share pointer values. The underlying SkRect array is
        copied when modified.

        Creating a SkRegion copy is very efficient and never allocates memory.
        SkRegion are always copied by value from the interface; the underlying shared
        pointers are not exposed.

        @param src  SkRegion to copy
        @return     copy of src
    */
    bool set(const SkRegion& src) {
        *this = src;
        return !this->isEmpty();
    }

    /** Exchanges SkIRect array of SkRegion and other. swap() internally exchanges pointers,
        so it is lightweight and does not allocate memory.

        swap() usage has largely been replaced by operator=(const SkRegion& region).
        SkPath do not copy their content on assignment until they are written to,
        making assignment as efficient as swap().

        @param other  operator=(const SkRegion& region) set
    */
    void swap(SkRegion& other);

    /** Returns true if SkRegion is empty.
        Empty SkRegion has bounds width or height less than or equal to zero.
        SkRegion() constructs empty SkRegion; setEmpty()
        and setRect() with dimensionless data make SkRegion empty.

        @return  true if bounds has no width or height
    */
    bool isEmpty() const { return fRunHead == emptyRunHeadPtr(); }

    /** Returns true if SkRegion is one SkIRect with positive dimensions.

        @return  true if SkRegion contains one SkIRect
    */
    bool isRect() const { return fRunHead == kRectRunHeadPtr; }

    /** Returns true if SkRegion is described by more than one rectangle.

        @return  true if SkRegion contains more than one SkIRect
    */
    bool isComplex() const { return !this->isEmpty() && !this->isRect(); }

    /** Returns minimum and maximum axes values of SkIRect array.
        Returns (0, 0, 0, 0) if SkRegion is empty.

        @return  combined bounds of all SkIRect elements
    */
    const SkIRect& getBounds() const { return fBounds; }

    /** Returns a value that increases with the number of
        elements in SkRegion. Returns zero if SkRegion is empty.
        Returns one if SkRegion equals SkIRect; otherwise, returns
        value greater than one indicating that SkRegion is complex.

        Call to compare SkRegion for relative complexity.

        @return  relative complexity
    */
    int computeRegionComplexity() const;

    /** Appends outline of SkRegion to path.
        Returns true if SkRegion is not empty; otherwise, returns false, and leaves path
        unmodified.

        @param path  SkPath to append to
        @return      true if path changed
    */
    bool getBoundaryPath(SkPath* path) const;

    /** Constructs an empty SkRegion. SkRegion is set to empty bounds
        at (0, 0) with zero width and height. Always returns false.

        @return  false
    */
    bool setEmpty();

    /** Constructs a rectangular SkRegion matching the bounds of rect.
        If rect is empty, constructs empty and returns false.

        @param rect  bounds of constructed SkRegion
        @return      true if rect is not empty
    */
    bool setRect(const SkIRect& rect);

    /** Constructs SkRegion with bounds (left, top, right, bottom).
        Returns true if left is less than right and top is less than bottom; otherwise,
        constructs empty SkRegion and returns false.

        @param left    edge of bounds on x-axis
        @param top     edge of bounds on y-axis
        @param right   edge of bounds on x-axis
        @param bottom  edge of bounds on y-axis
        @return        rectangular SkRegion
    */
    bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom) {
        return this->setRect({ left, top, right, bottom });
    }

    /** Constructs SkRegion as the union of SkIRect in rects array. If count is
        zero, constructs empty SkRegion. Returns false if constructed SkRegion is empty.

        May be faster than repeated calls to op().

        @param rects  array of SkIRect
        @param count  array size
        @return       true if constructed SkRegion is not empty
    */
    bool setRects(const SkIRect rects[], int count);

    /** Constructs a copy of an existing region.
        Makes two regions identical by value. Internally, region and
        the returned result share pointer values. The underlying SkRect array is
        copied when modified.

        Creating a SkRegion copy is very efficient and never allocates memory.
        SkRegion are always copied by value from the interface; the underlying shared
        pointers are not exposed.

        @param region  SkRegion to copy by value
        @return        SkRegion to copy by value
    */
    bool setRegion(const SkRegion& region);

    /** Constructs SkRegion to match outline of path within clip.
        Returns false if constructed SkRegion is empty.

        Constructed SkRegion draws the same pixels as path through clip when
        anti-aliasing is disabled.

        @param path  SkPath providing outline
        @param clip  SkRegion containing path
        @return      true if constructed SkRegion is not empty
    */
    bool setPath(const SkPath& path, const SkRegion& clip);

    /** Returns true if SkRegion intersects rect.
        Returns false if either rect or SkRegion is empty, or do not intersect.

        @param rect  SkIRect to intersect
        @return      true if rect and SkRegion have area in common
    */
    bool intersects(const SkIRect& rect) const;

    /** Returns true if SkRegion intersects other.
        Returns false if either other or SkRegion is empty, or do not intersect.

        @param other  SkRegion to intersect
        @return       true if other and SkRegion have area in common
    */
    bool intersects(const SkRegion& other) const;

    /** Returns true if SkIPoint (x, y) is inside SkRegion.
        Returns false if SkRegion is empty.

        @param x  test SkIPoint x-coordinate
        @param y  test SkIPoint y-coordinate
        @return   true if (x, y) is inside SkRegion
    */
    bool contains(int32_t x, int32_t y) const;

    /** Returns true if other is completely inside SkRegion.
        Returns false if SkRegion or other is empty.

        @param other  SkIRect to contain
        @return       true if other is inside SkRegion
    */
    bool contains(const SkIRect& other) const;

    /** Returns true if other is completely inside SkRegion.
        Returns false if SkRegion or other is empty.

        @param other  SkRegion to contain
        @return       true if other is inside SkRegion
    */
    bool contains(const SkRegion& other) const;

    /** Returns true if SkRegion is a single rectangle and contains r.
        May return false even though SkRegion contains r.

        @param r  SkIRect to contain
        @return   true quickly if r points are equal or inside
    */
    bool quickContains(const SkIRect& r) const {
        return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
    }

    /** Returns true if SkRegion is a single rectangle and contains SkIRect
        (left, top, right, bottom).
        Returns false if SkRegion is empty or SkIRect (left, top, right, bottom) is empty.
        May return false even though SkRegion contains (left, top, right, bottom).

        @param left    edge of bounds on x-axis
        @param top     edge of bounds on y-axis
        @param right   edge of bounds on x-axis
        @param bottom  edge of bounds on y-axis
        @return        true quickly if SkIRect are equal or inside
    */
    bool quickContains(int32_t left, int32_t top, int32_t right,
                       int32_t bottom) const {
        SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region

        return left < right && top < bottom &&
               fRunHead == kRectRunHeadPtr &&  // this->isRect()
               /* fBounds.contains(left, top, right, bottom); */
               fBounds.fLeft <= left && fBounds.fTop <= top &&
               fBounds.fRight >= right && fBounds.fBottom >= bottom;
    }

    /** Returns true if SkRegion does not intersect rect.
        Returns true if rect is empty or SkRegion is empty.
        May return false even though SkRegion does not intersect rect.

        @param rect  SkIRect to intersect
        @return      true if rect does not intersect
    */
    bool quickReject(const SkIRect& rect) const {
        return this->isEmpty() || rect.isEmpty() ||
                !SkIRect::Intersects(fBounds, rect);
    }

    /** Returns true if SkRegion does not intersect rgn.
        Returns true if rgn is empty or SkRegion is empty.
        May return false even though SkRegion does not intersect rgn.

        @param rgn  SkRegion to intersect
        @return     true if rgn does not intersect
    */
    bool quickReject(const SkRegion& rgn) const {
        return this->isEmpty() || rgn.isEmpty() ||
               !SkIRect::Intersects(fBounds, rgn.fBounds);
    }

    /** Offsets SkRegion by ivector (dx, dy). Has no effect if SkRegion is empty.

        @param dx  x-axis offset
        @param dy  y-axis offset
    */
    void translate(int dx, int dy) { this->translate(dx, dy, this); }

    /** Offsets SkRegion by ivector (dx, dy), writing result to dst. SkRegion may be passed
        as dst parameter, translating SkRegion in place. Has no effect if dst is nullptr.
        If SkRegion is empty, sets dst to empty.

        @param dx   x-axis offset
        @param dy   y-axis offset
        @param dst  translated result
    */
    void translate(int dx, int dy, SkRegion* dst) const;

    /** \enum SkRegion::Op
        The logical operations that can be performed when combining two SkRegion.
    */
    enum Op {
        kDifference_Op,                      //!< target minus operand
        kIntersect_Op,                       //!< target intersected with operand
        kUnion_Op,                           //!< target unioned with operand
        kXOR_Op,                             //!< target exclusive or with operand
        kReverseDifference_Op,               //!< operand minus target
        kReplace_Op,                         //!< replace target with operand
        kLastOp               = kReplace_Op, //!< last operator
    };

    static const int kOpCnt = kLastOp + 1;

    /** Replaces SkRegion with the result of SkRegion op rect.
        Returns true if replaced SkRegion is not empty.

        @param rect  SkIRect operand
        @param op    operator, one of:
                     kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
                     kReplace_Op
        @return      false if result is empty
    */
    bool op(const SkIRect& rect, Op op) {
        if (this->isRect() && kIntersect_Op == op) {
            if (!fBounds.intersect(rect)) {
                return this->setEmpty();
            }
            return true;
        }
        return this->op(*this, rect, op);
    }

    /** Replaces SkRegion with the result of SkRegion op SkIRect (left, top, right, bottom).
        Returns true if replaced SkRegion is not empty.

        @param left    edge of bounds on x-axis
        @param top     edge of bounds on y-axis
        @param right   edge of bounds on x-axis
        @param bottom  edge of bounds on y-axis
        @param op      operator, one of:
                       kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
                       kReplace_Op
        @return        false if result is empty
    */
    bool op(int left, int top, int right, int bottom, Op op) {
        SkIRect rect;
        rect.set(left, top, right, bottom);
        return this->op(*this, rect, op);
    }

    /** Replaces SkRegion with the result of SkRegion op rgn.
        Returns true if replaced SkRegion is not empty.

        @param rgn  SkRegion operand
        @param op   operator, one of:
                    kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
                    kReplace_Op
        @return     false if result is empty
    */
    bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }

    /** Replaces SkRegion with the result of rect op rgn.
        Returns true if replaced SkRegion is not empty.

        @param rect  SkIRect operand
        @param rgn   SkRegion operand
        @param op    operator, one of:
                     kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
                     kReplace_Op
        @return      false if result is empty
    */
    bool op(const SkIRect& rect, const SkRegion& rgn, Op op);

    /** Replaces SkRegion with the result of rgn op rect.
        Returns true if replaced SkRegion is not empty.

        @param rgn   SkRegion operand
        @param rect  SkIRect operand
        @param op    operator, one of:
                     kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
                     kReplace_Op
        @return      false if result is empty
    */
    bool op(const SkRegion& rgn, const SkIRect& rect, Op op);

    /** Replaces SkRegion with the result of rgna op rgnb.
        Returns true if replaced SkRegion is not empty.

        @param rgna  SkRegion operand
        @param rgnb  SkRegion operand
        @param op    operator, one of:
                     kDifference_Op, kIntersect_Op, kUnion_Op, kXOR_Op, kReverseDifference_Op,
                     kReplace_Op
        @return      false if result is empty
    */
    bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    /** Private. Android framework only.

        @return  string representation of SkRegion
    */
    char* toString();
#endif

    /** \class SkRegion::Iterator
        Returns sequence of rectangles, sorted along y-axis, then x-axis, that make
        up SkRegion.
    */
    class SK_API Iterator {
    public:

        /** Initializes SkRegion::Iterator with an empty SkRegion. done() on SkRegion::Iterator
            returns true.
            Call reset() to initialized SkRegion::Iterator at a later time.

            @return  empty SkRegion iterator
        */
        Iterator() : fRgn(nullptr), fDone(true) {}

        /** Sets SkRegion::Iterator to return elements of SkIRect array in region.

            @param region  SkRegion to iterate
            @return        SkRegion iterator
        */
        Iterator(const SkRegion& region);

        /** SkPoint SkRegion::Iterator to start of SkRegion.
            Returns true if SkRegion was set; otherwise, returns false.

            @return  true if SkRegion was set
        */
        bool rewind();

        /** Resets iterator, using the new SkRegion.

            @param region  SkRegion to iterate
        */
        void reset(const SkRegion& region);

        /** Returns true if SkRegion::Iterator is pointing to final SkIRect in SkRegion.

            @return  true if data parsing is complete
        */
        bool done() const { return fDone; }

        /** Advances SkRegion::Iterator to next SkIRect in SkRegion if it is not done.
        */
        void next();

        /** Returns SkIRect element in SkRegion. Does not return predictable results if SkRegion
            is empty.

            @return  part of SkRegion as SkIRect
        */
        const SkIRect& rect() const { return fRect; }

        /** Returns SkRegion if set; otherwise, returns nullptr.

            @return  iterated SkRegion
        */
        const SkRegion* rgn() const { return fRgn; }

    private:
        const SkRegion* fRgn;
        const SkRegion::RunType*  fRuns;
        SkIRect         fRect = {0, 0, 0, 0};
        bool            fDone;
    };

    /** \class SkRegion::Cliperator
        Returns the sequence of rectangles, sorted along y-axis, then x-axis, that make
        up SkRegion intersected with the specified clip rectangle.
    */
    class SK_API Cliperator {
    public:

        /** Sets SkRegion::Cliperator to return elements of SkIRect array in SkRegion within clip.

            @param region  SkRegion to iterate
            @param clip    bounds of iteration
            @return        SkRegion iterator
        */
        Cliperator(const SkRegion& region, const SkIRect& clip);

        /** Returns true if SkRegion::Cliperator is pointing to final SkIRect in SkRegion.

            @return  true if data parsing is complete
        */
        bool done() { return fDone; }

        /** Advances iterator to next SkIRect in SkRegion contained by clip.
        */
        void  next();

        /** Returns SkIRect element in SkRegion, intersected with clip passed to
            SkRegion::Cliperator constructor. Does not return predictable results if SkRegion
            is empty.

            @return  part of SkRegion inside clip as SkIRect
        */
        const SkIRect& rect() const { return fRect; }

    private:
        Iterator    fIter;
        SkIRect     fClip;
        SkIRect     fRect = {0, 0, 0, 0};
        bool        fDone;
    };

    /** \class SkRegion::Spanerator
        Returns the line segment ends within SkRegion that intersect a horizontal line.
    */
    class Spanerator {
    public:

        /** Sets SkRegion::Spanerator to return line segments in SkRegion on scan line.

            @param region  SkRegion to iterate
            @param y       horizontal line to intersect
            @param left    bounds of iteration
            @param right   bounds of iteration
            @return        SkRegion iterator
        */
        Spanerator(const SkRegion& region, int y, int left, int right);

        /** Advances iterator to next span intersecting SkRegion within line segment provided
            in constructor. Returns true if interval was found.

            @param left   pointer to span start; may be nullptr
            @param right  pointer to span end; may be nullptr
            @return       true if interval was found
        */
        bool next(int* left, int* right);

    private:
        const SkRegion::RunType* fRuns;
        int     fLeft, fRight;
        bool    fDone;
    };

    /** Writes SkRegion to buffer, and returns number of bytes written.
        If buffer is nullptr, returns number number of bytes that would be written.

        @param buffer  storage for binary data
        @return        size of SkRegion
    */
    size_t writeToMemory(void* buffer) const;

    /** Constructs SkRegion from buffer of size length. Returns bytes read.
        Returned value will be multiple of four or zero if length was too small.

        @param buffer  storage for binary data
        @param length  size of buffer
        @return        bytes read
    */
    size_t readFromMemory(const void* buffer, size_t length);

private:
    static constexpr int kOpCount = kReplace_Op + 1;

    // T
    // [B N L R S]
    // S
    static constexpr int kRectRegionRuns = 7;

    struct RunHead;

    static RunHead* emptyRunHeadPtr() { return (SkRegion::RunHead*) -1; }
    static constexpr RunHead* kRectRunHeadPtr = nullptr;

    // allocate space for count runs
    void allocateRuns(int count);
    void allocateRuns(int count, int ySpanCount, int intervalCount);
    void allocateRuns(const RunHead& src);

    SkDEBUGCODE(void dump() const;)

    SkIRect     fBounds;
    RunHead*    fRunHead;

    void freeRuns();

    /**
     *  Return the runs from this region, consing up fake runs if the region
     *  is empty or a rect. In those 2 cases, we use tmpStorage to hold the
     *  run data.
     */
    const RunType*  getRuns(RunType tmpStorage[], int* intervals) const;

    // This is called with runs[] that do not yet have their interval-count
    // field set on each scanline. That is computed as part of this call
    // (inside ComputeRunBounds).
    bool setRuns(RunType runs[], int count);

    int count_runtype_values(int* itop, int* ibot) const;

    bool isValid() const;

    static void BuildRectRuns(const SkIRect& bounds,
                              RunType runs[kRectRegionRuns]);

    // If the runs define a simple rect, return true and set bounds to that
    // rect. If not, return false and ignore bounds.
    static bool RunsAreARect(const SkRegion::RunType runs[], int count,
                             SkIRect* bounds);

    /**
     *  If the last arg is null, just return if the result is non-empty,
     *  else store the result in the last arg.
     */
    static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*);

    friend struct RunHead;
    friend class Iterator;
    friend class Spanerator;
    friend class SkRegionPriv;
    friend class SkRgnBuilder;
    friend class SkFlatRegion;
};

#endif
