LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkRegion.h (source / functions) Hit Total Coverage
Test: output.info Lines: 18 30 60.0 %
Date: 2017-07-14 16:53:18 Functions: 11 15 73.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13