Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2005 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkRegion_DEFINED
     11 #define SkRegion_DEFINED
     12 
     13 #include "SkRect.h"
     14 
     15 class SkPath;
     16 class SkRgnBuilder;
     17 
     18 namespace android {
     19     class Region;
     20 }
     21 
     22 #define SkRegion_gEmptyRunHeadPtr   ((SkRegion::RunHead*)-1)
     23 #define SkRegion_gRectRunHeadPtr    0
     24 
     25 /** \class SkRegion
     26 
     27     The SkRegion class encapsulates the geometric region used to specify
     28     clipping areas for drawing.
     29 */
     30 class SK_API SkRegion {
     31 public:
     32     typedef int32_t RunType;
     33     enum {
     34         kRunTypeSentinel = 0x7FFFFFFF
     35     };
     36 
     37     SkRegion();
     38     SkRegion(const SkRegion&);
     39     explicit SkRegion(const SkIRect&);
     40     ~SkRegion();
     41 
     42     SkRegion& operator=(const SkRegion&);
     43 
     44     /**
     45      *  Return true if the two regions are equal. i.e. The enclose exactly
     46      *  the same area.
     47      */
     48     bool operator==(const SkRegion& other) const;
     49 
     50     /**
     51      *  Return true if the two regions are not equal.
     52      */
     53     bool operator!=(const SkRegion& other) const {
     54         return !(*this == other);
     55     }
     56 
     57     /**
     58      *  Replace this region with the specified region, and return true if the
     59      *  resulting region is non-empty.
     60      */
     61     bool set(const SkRegion& src) {
     62         SkASSERT(&src);
     63         *this = src;
     64         return !this->isEmpty();
     65     }
     66 
     67     /**
     68      *  Swap the contents of this and the specified region. This operation
     69      *  is gauarenteed to never fail.
     70      */
     71     void swap(SkRegion&);
     72 
     73     /** Return true if this region is empty */
     74     bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; }
     75 
     76     /** Return true if this region is a single, non-empty rectangle */
     77     bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; }
     78 
     79     /** Return true if this region consists of more than 1 rectangular area */
     80     bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
     81 
     82     /**
     83      *  Return the bounds of this region. If the region is empty, returns an
     84      *  empty rectangle.
     85      */
     86     const SkIRect& getBounds() const { return fBounds; }
     87 
     88     /**
     89      *  Returns true if the region is non-empty, and if so, appends the
     90      *  boundary(s) of the region to the specified path.
     91      *  If the region is empty, returns false, and path is left unmodified.
     92      */
     93     bool getBoundaryPath(SkPath* path) const;
     94 
     95     /**
     96      *  Set the region to be empty, and return false, since the resulting
     97      *  region is empty
     98      */
     99     bool setEmpty();
    100 
    101     /**
    102      *  If rect is non-empty, set this region to that rectangle and return true,
    103      *  otherwise set this region to empty and return false.
    104      */
    105     bool setRect(const SkIRect&);
    106 
    107     /**
    108      *  If left < right and top < bottom, set this region to that rectangle and
    109      *  return true, otherwise set this region to empty and return false.
    110      */
    111     bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
    112 
    113     /**
    114      *  Set this region to the union of an array of rects. This is generally
    115      *  faster than calling region.op(rect, kUnion_Op) in a loop. If count is
    116      *  0, then this region is set to the empty region.
    117      *  @return true if the resulting region is non-empty
    118      */
    119     bool setRects(const SkIRect rects[], int count);
    120 
    121     /**
    122      *  Set this region to the specified region, and return true if it is
    123      *  non-empty.
    124      */
    125     bool setRegion(const SkRegion&);
    126 
    127     /**
    128      *  Set this region to the area described by the path, clipped.
    129      *  Return true if the resulting region is non-empty.
    130      *  This produces a region that is identical to the pixels that would be
    131      *  drawn by the path (with no antialiasing) with the specified clip.
    132      */
    133     bool setPath(const SkPath&, const SkRegion& clip);
    134 
    135     /**
    136      *  Returns true if the specified rectangle has a non-empty intersection
    137      *  with this region.
    138      */
    139     bool intersects(const SkIRect&) const;
    140 
    141     /**
    142      *  Returns true if the specified region has a non-empty intersection
    143      *  with this region.
    144      */
    145     bool intersects(const SkRegion&) const;
    146 
    147     /**
    148      *  Return true if the specified x,y coordinate is inside the region.
    149      */
    150     bool contains(int32_t x, int32_t y) const;
    151 
    152     /**
    153      *  Return true if the specified rectangle is completely inside the region.
    154      *  This works for simple (rectangular) and complex regions, and always
    155      *  returns the correct result. Note: if either this region or the rectangle
    156      *  is empty, contains() returns false.
    157      */
    158     bool contains(const SkIRect&) const;
    159 
    160     /**
    161      *  Return true if the specified region is completely inside the region.
    162      *  This works for simple (rectangular) and complex regions, and always
    163      *  returns the correct result. Note: if either region is empty, contains()
    164      *  returns false.
    165      */
    166     bool contains(const SkRegion&) const;
    167 
    168     /**
    169      *  Return true if this region is a single rectangle (not complex) and the
    170      *  specified rectangle is contained by this region. Returning false is not
    171      *  a guarantee that the rectangle is not contained by this region, but
    172      *  return true is a guarantee that the rectangle is contained by this region.
    173      */
    174     bool quickContains(const SkIRect& r) const {
    175         return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
    176     }
    177 
    178     /**
    179      *  Return true if this region is a single rectangle (not complex) and the
    180      *  specified rectangle is contained by this region. Returning false is not
    181      *  a guarantee that the rectangle is not contained by this region, but
    182      *  return true is a guarantee that the rectangle is contained by this
    183      *  region.
    184      */
    185     bool quickContains(int32_t left, int32_t top, int32_t right,
    186                        int32_t bottom) const {
    187         SkASSERT(this->isEmpty() == fBounds.isEmpty()); // valid region
    188 
    189         return left < right && top < bottom &&
    190                fRunHead == SkRegion_gRectRunHeadPtr &&  // this->isRect()
    191                /* fBounds.contains(left, top, right, bottom); */
    192                fBounds.fLeft <= left && fBounds.fTop <= top &&
    193                fBounds.fRight >= right && fBounds.fBottom >= bottom;
    194     }
    195 
    196     /**
    197      *  Return true if this region is empty, or if the specified rectangle does
    198      *  not intersect the region. Returning false is not a guarantee that they
    199      *  intersect, but returning true is a guarantee that they do not.
    200      */
    201     bool quickReject(const SkIRect& rect) const {
    202         return this->isEmpty() || rect.isEmpty() ||
    203                 !SkIRect::Intersects(fBounds, rect);
    204     }
    205 
    206     /**
    207      *  Return true if this region, or rgn, is empty, or if their bounds do not
    208      *  intersect. Returning false is not a guarantee that they intersect, but
    209      *  returning true is a guarantee that they do not.
    210      */
    211     bool quickReject(const SkRegion& rgn) const {
    212         return this->isEmpty() || rgn.isEmpty() ||
    213                !SkIRect::Intersects(fBounds, rgn.fBounds);
    214     }
    215 
    216     /** Translate the region by the specified (dx, dy) amount. */
    217     void translate(int dx, int dy) { this->translate(dx, dy, this); }
    218 
    219     /**
    220      *  Translate the region by the specified (dx, dy) amount, writing the
    221      *  resulting region into dst. Note: it is legal to pass this region as the
    222      *  dst parameter, effectively translating the region in place. If dst is
    223      *  null, nothing happens.
    224      */
    225     void translate(int dx, int dy, SkRegion* dst) const;
    226 
    227     /**
    228      *  The logical operations that can be performed when combining two regions.
    229      */
    230     enum Op {
    231         kDifference_Op, //!< subtract the op region from the first region
    232         kIntersect_Op,  //!< intersect the two regions
    233         kUnion_Op,      //!< union (inclusive-or) the two regions
    234         kXOR_Op,        //!< exclusive-or the two regions
    235         /** subtract the first region from the op region */
    236         kReverseDifference_Op,
    237         kReplace_Op     //!< replace the dst region with the op region
    238     };
    239 
    240     /**
    241      *  Set this region to the result of applying the Op to this region and the
    242      *  specified rectangle: this = (this op rect).
    243      *  Return true if the resulting region is non-empty.
    244      */
    245     bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); }
    246 
    247     /**
    248      *  Set this region to the result of applying the Op to this region and the
    249      *  specified rectangle: this = (this op rect).
    250      *  Return true if the resulting region is non-empty.
    251      */
    252     bool op(int left, int top, int right, int bottom, Op op) {
    253         SkIRect rect;
    254         rect.set(left, top, right, bottom);
    255         return this->op(*this, rect, op);
    256     }
    257 
    258     /**
    259      *  Set this region to the result of applying the Op to this region and the
    260      *  specified region: this = (this op rgn).
    261      *  Return true if the resulting region is non-empty.
    262      */
    263     bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
    264 
    265     /**
    266      *  Set this region to the result of applying the Op to the specified
    267      *  rectangle and region: this = (rect op rgn).
    268      *  Return true if the resulting region is non-empty.
    269      */
    270     bool op(const SkIRect& rect, const SkRegion& rgn, Op);
    271 
    272     /**
    273      *  Set this region to the result of applying the Op to the specified
    274      *  region and rectangle: this = (rgn op rect).
    275      *  Return true if the resulting region is non-empty.
    276      */
    277     bool op(const SkRegion& rgn, const SkIRect& rect, Op);
    278 
    279     /**
    280      *  Set this region to the result of applying the Op to the specified
    281      *  regions: this = (rgna op rgnb).
    282      *  Return true if the resulting region is non-empty.
    283      */
    284     bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
    285 
    286 #ifdef SK_BUILD_FOR_ANDROID
    287     /** Returns a new char* containing the list of rectangles in this region
    288      */
    289     char* toString();
    290 #endif
    291 
    292     /**
    293      *  Returns the sequence of rectangles, sorted in Y and X, that make up
    294      *  this region.
    295      */
    296     class SK_API Iterator {
    297     public:
    298         Iterator() : fRgn(NULL), fDone(true) {}
    299         Iterator(const SkRegion&);
    300         // if we have a region, reset to it and return true, else return false
    301         bool rewind();
    302         // reset the iterator, using the new region
    303         void reset(const SkRegion&);
    304         bool done() const { return fDone; }
    305         void next();
    306         const SkIRect& rect() const { return fRect; }
    307         // may return null
    308         const SkRegion* rgn() const { return fRgn; }
    309 
    310     private:
    311         const SkRegion* fRgn;
    312         const RunType*  fRuns;
    313         SkIRect         fRect;
    314         bool            fDone;
    315     };
    316 
    317     /**
    318      *  Returns the sequence of rectangles, sorted in Y and X, that make up
    319      *  this region intersected with the specified clip rectangle.
    320      */
    321     class SK_API Cliperator {
    322     public:
    323         Cliperator(const SkRegion&, const SkIRect& clip);
    324         bool done() { return fDone; }
    325         void  next();
    326         const SkIRect& rect() const { return fRect; }
    327 
    328     private:
    329         Iterator    fIter;
    330         SkIRect     fClip;
    331         SkIRect     fRect;
    332         bool        fDone;
    333     };
    334 
    335     /**
    336      *  Returns the sequence of runs that make up this region for the specified
    337      *  Y scanline, clipped to the specified left and right X values.
    338      */
    339     class Spanerator {
    340     public:
    341         Spanerator(const SkRegion&, int y, int left, int right);
    342         bool next(int* left, int* right);
    343 
    344     private:
    345         const SkRegion::RunType* fRuns;
    346         int     fLeft, fRight;
    347         bool    fDone;
    348     };
    349 
    350     /**
    351      *  Write the region to the buffer, and return the number of bytes written.
    352      *  If buffer is NULL, it still returns the number of bytes.
    353      */
    354     uint32_t writeToMemory(void* buffer) const;
    355 
    356     /**
    357      *  Initialized the region from the buffer, returning the number
    358      *  of bytes actually read.
    359      */
    360     uint32_t readFromMemory(const void* buffer);
    361 
    362     /**
    363      *  Returns a reference to a global empty region. Just a convenience for
    364      *  callers that need a const empty region.
    365      */
    366     static const SkRegion& GetEmptyRegion();
    367 
    368     SkDEBUGCODE(void dump() const;)
    369     SkDEBUGCODE(void validate() const;)
    370     SkDEBUGCODE(static void UnitTest();)
    371 
    372     // expose this to allow for regression test on complex regions
    373     SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);)
    374 
    375 private:
    376     enum {
    377         kOpCount = kReplace_Op + 1
    378     };
    379 
    380     enum {
    381         // T
    382         // [B N L R S]
    383         // S
    384         kRectRegionRuns = 7
    385     };
    386 
    387     friend class android::Region;    // needed for marshalling efficiently
    388 
    389     struct RunHead;
    390 
    391     // allocate space for count runs
    392     void allocateRuns(int count);
    393     void allocateRuns(int count, int ySpanCount, int intervalCount);
    394     void allocateRuns(const RunHead& src);
    395 
    396     SkIRect     fBounds;
    397     RunHead*    fRunHead;
    398 
    399     void freeRuns();
    400 
    401     /**
    402      *  Return the runs from this region, consing up fake runs if the region
    403      *  is empty or a rect. In those 2 cases, we use tmpStorage to hold the
    404      *  run data.
    405      */
    406     const RunType*  getRuns(RunType tmpStorage[], int* intervals) const;
    407 
    408     // This is called with runs[] that do not yet have their interval-count
    409     // field set on each scanline. That is computed as part of this call
    410     // (inside ComputeRunBounds).
    411     bool setRuns(RunType runs[], int count);
    412 
    413     int count_runtype_values(int* itop, int* ibot) const;
    414 
    415     static void BuildRectRuns(const SkIRect& bounds,
    416                               RunType runs[kRectRegionRuns]);
    417 
    418     // If the runs define a simple rect, return true and set bounds to that
    419     // rect. If not, return false and ignore bounds.
    420     static bool RunsAreARect(const SkRegion::RunType runs[], int count,
    421                              SkIRect* bounds);
    422 
    423     /**
    424      *  If the last arg is null, just return if the result is non-empty,
    425      *  else store the result in the last arg.
    426      */
    427     static bool Oper(const SkRegion&, const SkRegion&, SkRegion::Op, SkRegion*);
    428 
    429     friend struct RunHead;
    430     friend class Iterator;
    431     friend class Spanerator;
    432     friend class SkRgnBuilder;
    433     friend class SkFlatRegion;
    434 };
    435 
    436 #endif
    437