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