• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 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 package android.graphics;
18 
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 
22 public class Region implements Parcelable {
23 
24     // the native values for these must match up with the enum in SkRegion.h
25     public enum Op {
26         DIFFERENCE(0),
27         INTERSECT(1),
28         UNION(2),
29         XOR(3),
30         REVERSE_DIFFERENCE(4),
31         REPLACE(5);
32 
Op(int nativeInt)33         Op(int nativeInt) {
34             this.nativeInt = nativeInt;
35         }
36         final int nativeInt;
37     }
38 
39     /** Create an empty region
40     */
Region()41     public Region() {
42         this(nativeConstructor());
43     }
44 
45     /** Return a copy of the specified region
46     */
Region(Region region)47     public Region(Region region) {
48         this(nativeConstructor());
49         nativeSetRegion(mNativeRegion, region.mNativeRegion);
50     }
51 
52     /** Return a region set to the specified rectangle
53     */
Region(Rect r)54     public Region(Rect r) {
55         mNativeRegion = nativeConstructor();
56         nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
57     }
58 
59     /** Return a region set to the specified rectangle
60     */
Region(int left, int top, int right, int bottom)61     public Region(int left, int top, int right, int bottom) {
62         mNativeRegion = nativeConstructor();
63         nativeSetRect(mNativeRegion, left, top, right, bottom);
64     }
65 
66     /** Set the region to the empty region
67     */
setEmpty()68     public void setEmpty() {
69         nativeSetRect(mNativeRegion, 0, 0, 0, 0);
70     }
71 
72     /** Set the region to the specified region.
73     */
set(Region region)74     public boolean set(Region region) {
75         return nativeSetRegion(mNativeRegion, region.mNativeRegion);
76     }
77 
78     /** Set the region to the specified rectangle
79     */
set(Rect r)80     public boolean set(Rect r) {
81         return nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
82     }
83 
84     /** Set the region to the specified rectangle
85     */
set(int left, int top, int right, int bottom)86     public boolean set(int left, int top, int right, int bottom) {
87         return nativeSetRect(mNativeRegion, left, top, right, bottom);
88     }
89 
90     /**
91      * Set the region to the area described by the path and clip.
92      * Return true if the resulting region is non-empty. This produces a region
93      * that is identical to the pixels that would be drawn by the path
94      * (with no antialiasing).
95      */
setPath(Path path, Region clip)96     public boolean setPath(Path path, Region clip) {
97         return nativeSetPath(mNativeRegion, path.ni(), clip.mNativeRegion);
98     }
99 
100     /**
101      * Return true if this region is empty
102      */
isEmpty()103     public native boolean isEmpty();
104 
105     /**
106      * Return true if the region contains a single rectangle
107      */
isRect()108     public native boolean isRect();
109 
110     /**
111      * Return true if the region contains more than one rectangle
112      */
isComplex()113     public native boolean isComplex();
114 
115     /**
116      * Return a new Rect set to the bounds of the region. If the region is
117      * empty, the Rect will be set to [0, 0, 0, 0]
118      */
getBounds()119     public Rect getBounds() {
120         Rect r = new Rect();
121         nativeGetBounds(mNativeRegion, r);
122         return r;
123     }
124 
125     /**
126      * Set the Rect to the bounds of the region. If the region is empty, the
127      * Rect will be set to [0, 0, 0, 0]
128      */
getBounds(Rect r)129     public boolean getBounds(Rect r) {
130         if (r == null) {
131             throw new NullPointerException();
132         }
133         return nativeGetBounds(mNativeRegion, r);
134     }
135 
136     /**
137      * Return the boundary of the region as a new Path. If the region is empty,
138      * the path will also be empty.
139      */
getBoundaryPath()140     public Path getBoundaryPath() {
141         Path path = new Path();
142         nativeGetBoundaryPath(mNativeRegion, path.ni());
143         return path;
144     }
145 
146     /**
147      * Set the path to the boundary of the region. If the region is empty, the
148      * path will also be empty.
149      */
getBoundaryPath(Path path)150     public boolean getBoundaryPath(Path path) {
151         return nativeGetBoundaryPath(mNativeRegion, path.ni());
152     }
153 
154     /**
155      * Return true if the region contains the specified point
156      */
contains(int x, int y)157     public native boolean contains(int x, int y);
158 
159     /**
160      * Return true if the region is a single rectangle (not complex) and it
161      * contains the specified rectangle. Returning false is not a guarantee
162      * that the rectangle is not contained by this region, but return true is a
163      * guarantee that the rectangle is contained by this region.
164      */
quickContains(Rect r)165     public boolean quickContains(Rect r) {
166         return quickContains(r.left, r.top, r.right, r.bottom);
167     }
168 
169     /**
170      * Return true if the region is a single rectangle (not complex) and it
171      * contains the specified rectangle. Returning false is not a guarantee
172      * that the rectangle is not contained by this region, but return true is a
173      * guarantee that the rectangle is contained by this region.
174      */
quickContains(int left, int top, int right, int bottom)175     public native boolean quickContains(int left, int top, int right,
176                                         int bottom);
177 
178     /**
179      * Return true if the region is empty, or if the specified rectangle does
180      * not intersect the region. Returning false is not a guarantee that they
181      * intersect, but returning true is a guarantee that they do not.
182      */
quickReject(Rect r)183     public boolean quickReject(Rect r) {
184         return quickReject(r.left, r.top, r.right, r.bottom);
185     }
186 
187     /**
188      * Return true if the region is empty, or if the specified rectangle does
189      * not intersect the region. Returning false is not a guarantee that they
190      * intersect, but returning true is a guarantee that they do not.
191      */
quickReject(int left, int top, int right, int bottom)192     public native boolean quickReject(int left, int top, int right, int bottom);
193 
194     /**
195      * Return true if the region is empty, or if the specified region does not
196      * intersect the region. Returning false is not a guarantee that they
197      * intersect, but returning true is a guarantee that they do not.
198      */
quickReject(Region rgn)199     public native boolean quickReject(Region rgn);
200 
201     /**
202      * Translate the region by [dx, dy]. If the region is empty, do nothing.
203      */
translate(int dx, int dy)204     public void translate(int dx, int dy) {
205         translate(dx, dy, null);
206     }
207 
208     /**
209      * Set the dst region to the result of translating this region by [dx, dy].
210      * If this region is empty, then dst will be set to empty.
211      */
translate(int dx, int dy, Region dst)212     public native void translate(int dx, int dy, Region dst);
213 
214     /**
215      * Scale the region by the given scale amount. This re-constructs new region by
216      * scaling the rects that this region consists of. New rectis are computed by scaling
217      * coordinates by float, then rounded by roundf() function to integers. This may results
218      * in less internal rects if 0 < scale < 1. Zero and Negative scale result in
219      * an empty region. If this region is empty, do nothing.
220      *
221      * @hide
222      */
scale(float scale)223     public void scale(float scale) {
224         scale(scale, null);
225     }
226 
227     /**
228      * Set the dst region to the result of scaling this region by the given scale amount.
229      * If this region is empty, then dst will be set to empty.
230      * @hide
231      */
scale(float scale, Region dst)232     public native void scale(float scale, Region dst);
233 
union(Rect r)234     public final boolean union(Rect r) {
235         return op(r, Op.UNION);
236     }
237 
238     /**
239      * Perform the specified Op on this region and the specified rect. Return
240      * true if the result of the op is not empty.
241      */
op(Rect r, Op op)242     public boolean op(Rect r, Op op) {
243         return nativeOp(mNativeRegion, r.left, r.top, r.right, r.bottom,
244                         op.nativeInt);
245     }
246 
247     /**
248      * Perform the specified Op on this region and the specified rect. Return
249      * true if the result of the op is not empty.
250      */
op(int left, int top, int right, int bottom, Op op)251     public boolean op(int left, int top, int right, int bottom, Op op) {
252         return nativeOp(mNativeRegion, left, top, right, bottom,
253                         op.nativeInt);
254     }
255 
256     /**
257      * Perform the specified Op on this region and the specified region. Return
258      * true if the result of the op is not empty.
259      */
op(Region region, Op op)260     public boolean op(Region region, Op op) {
261         return op(this, region, op);
262     }
263 
264     /**
265      * Set this region to the result of performing the Op on the specified rect
266      * and region. Return true if the result is not empty.
267      */
op(Rect rect, Region region, Op op)268     public boolean op(Rect rect, Region region, Op op) {
269         return nativeOp(mNativeRegion, rect, region.mNativeRegion,
270                         op.nativeInt);
271     }
272 
273     /**
274      * Set this region to the result of performing the Op on the specified
275      * regions. Return true if the result is not empty.
276      */
op(Region region1, Region region2, Op op)277     public boolean op(Region region1, Region region2, Op op) {
278         return nativeOp(mNativeRegion, region1.mNativeRegion,
279                         region2.mNativeRegion, op.nativeInt);
280     }
281 
282     //////////////////////////////////////////////////////////////////////////
283 
284     public static final Parcelable.Creator<Region> CREATOR
285         = new Parcelable.Creator<Region>() {
286             /**
287             * Rebuild a Region previously stored with writeToParcel().
288              * @param p    Parcel object to read the region from
289              * @return a new region created from the data in the parcel
290              */
291             public Region createFromParcel(Parcel p) {
292                 int ni = nativeCreateFromParcel(p);
293                 if (ni == 0) {
294                     throw new RuntimeException();
295                 }
296                 return new Region(ni);
297             }
298             public Region[] newArray(int size) {
299                 return new Region[size];
300             }
301     };
302 
describeContents()303     public int describeContents() {
304         return 0;
305     }
306 
307     /**
308      * Write the region and its pixels to the parcel. The region can be
309      * rebuilt from the parcel by calling CREATOR.createFromParcel().
310      * @param p    Parcel object to write the region data into
311      */
writeToParcel(Parcel p, int flags)312     public void writeToParcel(Parcel p, int flags) {
313         if (!nativeWriteToParcel(mNativeRegion, p)) {
314             throw new RuntimeException();
315         }
316     }
317 
318     @Override
equals(Object obj)319     public boolean equals(Object obj) {
320         if (obj == null || !(obj instanceof Region)) {
321             return false;
322         }
323         Region peer = (Region) obj;
324         return nativeEquals(mNativeRegion, peer.mNativeRegion);
325     }
326 
finalize()327     protected void finalize() throws Throwable {
328         nativeDestructor(mNativeRegion);
329     }
330 
Region(int ni)331     /*package*/ Region(int ni) {
332         if (ni == 0) {
333             throw new RuntimeException();
334         }
335         mNativeRegion = ni;
336     }
337 
338     /* add dummy parameter so constructor can be called from jni without
339        triggering 'not cloneable' exception */
Region(int ni, int dummy)340     private Region(int ni, int dummy) {
341         this(ni);
342     }
343 
ni()344     /*package*/ final int ni() {
345         return mNativeRegion;
346     }
347 
nativeConstructor()348     private static native int nativeConstructor();
nativeDestructor(int native_region)349     private static native void nativeDestructor(int native_region);
350 
nativeSetRegion(int native_dst, int native_src)351     private static native boolean nativeSetRegion(int native_dst,
352                                                   int native_src);
nativeSetRect(int native_dst, int left, int top, int right, int bottom)353     private static native boolean nativeSetRect(int native_dst, int left,
354                                                 int top, int right, int bottom);
nativeSetPath(int native_dst, int native_path, int native_clip)355     private static native boolean nativeSetPath(int native_dst, int native_path,
356                                                 int native_clip);
nativeGetBounds(int native_region, Rect rect)357     private static native boolean nativeGetBounds(int native_region, Rect rect);
nativeGetBoundaryPath(int native_region, int native_path)358     private static native boolean nativeGetBoundaryPath(int native_region,
359                                                         int native_path);
360 
nativeOp(int native_dst, int left, int top, int right, int bottom, int op)361     private static native boolean nativeOp(int native_dst, int left, int top,
362                                            int right, int bottom, int op);
nativeOp(int native_dst, Rect rect, int native_region, int op)363     private static native boolean nativeOp(int native_dst, Rect rect,
364                                            int native_region, int op);
nativeOp(int native_dst, int native_region1, int native_region2, int op)365     private static native boolean nativeOp(int native_dst, int native_region1,
366                                            int native_region2, int op);
367 
nativeCreateFromParcel(Parcel p)368     private static native int nativeCreateFromParcel(Parcel p);
nativeWriteToParcel(int native_region, Parcel p)369     private static native boolean nativeWriteToParcel(int native_region,
370                                                       Parcel p);
371 
nativeEquals(int native_r1, int native_r2)372     private static native boolean nativeEquals(int native_r1, int native_r2);
373 
374     private final int mNativeRegion;
375 }
376