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