00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef SkRegion_DEFINED
00018 #define SkRegion_DEFINED
00019
00020 #include "SkRect.h"
00021
00022 class SkPath;
00023 class SkRgnBuilder;
00024
00025 namespace android {
00026 class Region;
00027 }
00028
00029 #define SkRegion_gEmptyRunHeadPtr ((SkRegion::RunHead*)-1)
00030 #define SkRegion_gRectRunHeadPtr 0
00031
00037 class SkRegion {
00038 public:
00039 typedef int32_t RunType;
00040 enum {
00041 kRunTypeSentinel = 0x7FFFFFFF
00042 };
00043
00044 SkRegion();
00045 SkRegion(const SkRegion&);
00046 explicit SkRegion(const SkIRect&);
00047 ~SkRegion();
00048
00049 SkRegion& operator=(const SkRegion&);
00050
00051 friend int operator==(const SkRegion& a, const SkRegion& b);
00052 friend int operator!=(const SkRegion& a, const SkRegion& b) {
00053 return !(a == b);
00054 }
00055
00059 bool set(const SkRegion& src) {
00060 SkASSERT(&src);
00061 *this = src;
00062 return !this->isEmpty();
00063 }
00064
00068 void swap(SkRegion&);
00069
00071 bool isEmpty() const { return fRunHead == SkRegion_gEmptyRunHeadPtr; }
00073 bool isRect() const { return fRunHead == SkRegion_gRectRunHeadPtr; }
00075 bool isComplex() const { return !this->isEmpty() && !this->isRect(); }
00079 const SkIRect& getBounds() const { return fBounds; }
00080
00084 bool getBoundaryPath(SkPath* path) const;
00085
00089 bool setEmpty();
00090
00094 bool setRect(const SkIRect&);
00095
00099 bool setRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
00100
00103 bool setRegion(const SkRegion&);
00104
00110 bool setPath(const SkPath&, const SkRegion& clip);
00111
00115 bool intersects(const SkIRect&) const;
00116
00120 bool intersects(const SkRegion&) const;
00121
00124 bool contains(int32_t x, int32_t y) const;
00125
00131 bool contains(const SkIRect&) const;
00132
00138 bool contains(const SkRegion&) const;
00139
00145 bool quickContains(const SkIRect& r) const {
00146 return this->quickContains(r.fLeft, r.fTop, r.fRight, r.fBottom);
00147 }
00148
00155 bool quickContains(int32_t left, int32_t top, int32_t right,
00156 int32_t bottom) const {
00157 SkASSERT(this->isEmpty() == fBounds.isEmpty());
00158
00159 return left < right && top < bottom &&
00160 fRunHead == SkRegion_gRectRunHeadPtr &&
00161
00162 fBounds.fLeft <= left && fBounds.fTop <= top &&
00163 fBounds.fRight >= right && fBounds.fBottom >= bottom;
00164 }
00165
00170 bool quickReject(const SkIRect& rect) const
00171 {
00172 return this->isEmpty() || rect.isEmpty() ||
00173 !SkIRect::Intersects(fBounds, rect);
00174 }
00175
00180 bool quickReject(const SkRegion& rgn) const {
00181 return this->isEmpty() || rgn.isEmpty() ||
00182 !SkIRect::Intersects(fBounds, rgn.fBounds);
00183 }
00184
00187 void translate(int dx, int dy) { this->translate(dx, dy, this); }
00188
00194 void translate(int dx, int dy, SkRegion* dst) const;
00195
00198 enum Op {
00199 kDifference_Op,
00200 kIntersect_Op,
00201 kUnion_Op,
00202 kXOR_Op,
00203
00204 kReverseDifference_Op,
00205 kReplace_Op
00206 };
00207
00212 bool op(const SkIRect& rect, Op op) { return this->op(*this, rect, op); }
00213
00218 bool op(int left, int top, int right, int bottom, Op op) {
00219 SkIRect rect;
00220 rect.set(left, top, right, bottom);
00221 return this->op(*this, rect, op);
00222 }
00223
00228 bool op(const SkRegion& rgn, Op op) { return this->op(*this, rgn, op); }
00233 bool op(const SkIRect& rect, const SkRegion& rgn, Op);
00238 bool op(const SkRegion& rgn, const SkIRect& rect, Op);
00243 bool op(const SkRegion& rgna, const SkRegion& rgnb, Op op);
00244
00248 class Iterator {
00249 public:
00250 Iterator() : fRgn(NULL), fDone(true) {}
00251 Iterator(const SkRegion&);
00252
00253 bool rewind();
00254
00255 void reset(const SkRegion&);
00256 bool done() { return fDone; }
00257 void next();
00258 const SkIRect& rect() const { return fRect; }
00259
00260 private:
00261 const SkRegion* fRgn;
00262 const RunType* fRuns;
00263 SkIRect fRect;
00264 bool fDone;
00265 };
00266
00270 class Cliperator {
00271 public:
00272 Cliperator(const SkRegion&, const SkIRect& clip);
00273 bool done() { return fDone; }
00274 void next();
00275 const SkIRect& rect() const { return fRect; }
00276
00277 private:
00278 Iterator fIter;
00279 SkIRect fClip;
00280 SkIRect fRect;
00281 bool fDone;
00282 };
00283
00287 class Spanerator {
00288 public:
00289 Spanerator(const SkRegion&, int y, int left, int right);
00290 bool next(int* left, int* right);
00291
00292 private:
00293 const SkRegion::RunType* fRuns;
00294 int fLeft, fRight;
00295 bool fDone;
00296 };
00297
00301 uint32_t flatten(void* buffer) const;
00305 uint32_t unflatten(const void* buffer);
00306
00307 SkDEBUGCODE(void dump() const;)
00308 SkDEBUGCODE(void validate() const;)
00309 SkDEBUGCODE(static void UnitTest();)
00310
00311
00312 SkDEBUGCODE(bool debugSetRuns(const RunType runs[], int count);)
00313
00314 private:
00315 enum {
00316 kOpCount = kReplace_Op + 1
00317 };
00318
00319 enum {
00320 kRectRegionRuns = 6
00321 };
00322
00323 friend class android::Region;
00324 void allocateRuns(int count);
00325
00326 struct RunHead;
00327
00328 SkIRect fBounds;
00329 RunHead* fRunHead;
00330
00331 void freeRuns();
00332 const RunType* getRuns(RunType tmpStorage[], int* count) const;
00333 bool setRuns(RunType runs[], int count);
00334
00335 int count_runtype_values(int* itop, int* ibot) const;
00336
00337 static void BuildRectRuns(const SkIRect& bounds,
00338 RunType runs[kRectRegionRuns]);
00339
00340 static bool ComputeRunBounds(const RunType runs[], int count,
00341 SkIRect* bounds);
00342
00343 friend struct RunHead;
00344 friend class Iterator;
00345 friend class Spanerator;
00346 friend class SkRgnBuilder;
00347 friend class SkFlatRegion;
00348 };
00349
00350
00351 #endif
00352