/*
 * 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 "include/core/SkRect.h"
#include "include/private/base/SkAPI.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkTypeTraits.h"

#include <cstddef>
#include <cstdint>
#include <type_traits>

class SkPath;

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

        example: https://fiddle.skia.org/c/@Region_empty_constructor
    */
    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

        example: https://fiddle.skia.org/c/@Region_copy_const_SkRegion
    */
    SkRegion(const SkRegion& region);

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

        @param rect  bounds of constructed SkRegion
        @return      rectangular SkRegion

        example: https://fiddle.skia.org/c/@Region_copy_const_SkIRect
    */
    explicit SkRegion(const SkIRect& rect);

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

        example: https://fiddle.skia.org/c/@Region_destructor
    */
    ~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

        example: https://fiddle.skia.org/c/@Region_copy_operator
    */
    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

        example: https://fiddle.skia.org/c/@Region_equal1_operator
    */
    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

        example: https://fiddle.skia.org/c/@Region_swap
    */
    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

        example: https://fiddle.skia.org/c/@Region_computeRegionComplexity
    */
    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

        example: https://fiddle.skia.org/c/@Region_getBoundaryPath
    */
    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

        example: https://fiddle.skia.org/c/@Region_setEmpty
    */
    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

        example: https://fiddle.skia.org/c/@Region_setRect
    */
    bool setRect(const SkIRect& rect);

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

        example: https://fiddle.skia.org/c/@Region_setRects
    */
    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

        example: https://fiddle.skia.org/c/@Region_setRegion
    */
    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

        example: https://fiddle.skia.org/c/@Region_setPath
    */
    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

        example: https://fiddle.skia.org/c/@Region_intersects
    */
    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

        example: https://fiddle.skia.org/c/@Region_intersects_2
    */
    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

        example: https://fiddle.skia.org/c/@Region_contains
    */
    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

        example: https://fiddle.skia.org/c/@Region_contains_2
    */
    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

        example: https://fiddle.skia.org/c/@Region_contains_3
    */
    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 {
        SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region

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

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

        example: https://fiddle.skia.org/c/@Region_translate_2
    */
    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
        @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 rgn.
        Returns true if replaced SkRegion is not empty.

        @param rgn  SkRegion operand
        @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
        @return      false if result is empty

        example: https://fiddle.skia.org/c/@Region_op_4
    */
    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
        @return      false if result is empty

        example: https://fiddle.skia.org/c/@Region_op_5
    */
    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
        @return      false if result is empty

        example: https://fiddle.skia.org/c/@Region_op_6
    */
    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

        example: https://fiddle.skia.org/c/@Region_Iterator_copy_const_SkRegion
        */
        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

        example: https://fiddle.skia.org/c/@Region_Iterator_rewind
        */
        bool rewind();

        /** Resets iterator, using the new SkRegion.

            @param region  SkRegion to iterate

        example: https://fiddle.skia.org/c/@Region_Iterator_reset
        */
        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.

        example: https://fiddle.skia.org/c/@Region_Iterator_next
        */
        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

        example: https://fiddle.skia.org/c/@Region_Cliperator_const_SkRegion_const_SkIRect
        */
        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.

        example: https://fiddle.skia.org/c/@Region_Cliperator_next
        */
        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

        example: https://fiddle.skia.org/c/@Region_Spanerator_const_SkRegion_int_int_int
        */
        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

        example: https://fiddle.skia.org/c/@Region_Spanerator_next
        */
        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

        example: https://fiddle.skia.org/c/@Region_writeToMemory
    */
    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

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

    using sk_is_trivially_relocatable = std::true_type;

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;

    static_assert(::sk_is_trivially_relocatable<decltype(fBounds)>::value);
    static_assert(::sk_is_trivially_relocatable<decltype(fRunHead)>::value);

    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
