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