|
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 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 */ |
|
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 */ |
|
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 */ |
|
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 */ |
|
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. */ |
|
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 */ |
|
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 */ |
|
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 */ |
|
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: |
|
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&); |
|
314 bool done() const { return fDone; } |
|
315 void next(); |
|
316 const SkIRect& rect() const { return fRect; } |
|
317 // may return null |
|
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); |
|
334 bool done() { return fDone; } |
|
335 void next(); |
|
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 |