OSDN Git Service

DO NOT MERGE. Grant MMS Uri permissions as the calling UID.
[android-x86/frameworks-base.git] / graphics / java / android / graphics / Region.java
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
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     */
56     public Region() {
57         this(nativeConstructor());
58     }
59
60     /** Return a copy of the specified region
61     */
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     */
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     */
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     */
83     public void setEmpty() {
84         nativeSetRect(mNativeRegion, 0, 0, 0, 0);
85     }
86
87     /** Set the region to the specified region.
88     */
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     */
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     */
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      */
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      */
119     public native boolean isEmpty();
120     
121     /**
122      * Return true if the region contains a single rectangle
123      */
124     public native boolean isRect();
125     
126     /**
127      * Return true if the region contains more than one rectangle
128      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
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      */
215     public native boolean quickReject(Region rgn);
216
217     /**
218      * Translate the region by [dx, dy]. If the region is empty, do nothing.
219      */
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      */
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      */
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      */
248     public native void scale(float scale, Region dst);
249
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      */
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      */
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      */
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      */
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      */
293     public boolean op(Region region1, Region region2, Op op) {
294         return nativeOp(mNativeRegion, region1.mNativeRegion,
295                         region2.mNativeRegion, op.nativeInt);
296     }
297
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      */
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      */
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      */
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     
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      */
365     public void writeToParcel(Parcel p, int flags) {
366         if (!nativeWriteToParcel(mNativeRegion, p)) {
367             throw new RuntimeException();
368         }
369     }
370
371     @Override
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
380     protected void finalize() throws Throwable {
381         try {
382             nativeDestructor(mNativeRegion);
383             mNativeRegion = 0;
384         } finally {
385             super.finalize();
386         }
387     }
388     
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 */
398     private Region(long ni, int dummy) {
399         this(ni);
400     }
401
402     final long ni() {
403         return mNativeRegion;
404     }
405
406     private static native boolean nativeEquals(long native_r1, long native_r2);
407
408     private static native long nativeConstructor();
409     private static native void nativeDestructor(long native_region);
410
411     private static native void nativeSetRegion(long native_dst, long native_src);
412     private static native boolean nativeSetRect(long native_dst, int left,
413                                                 int top, int right, int bottom);
414     private static native boolean nativeSetPath(long native_dst, long native_path,
415                                                 long native_clip);
416     private static native boolean nativeGetBounds(long native_region, Rect rect);
417     private static native boolean nativeGetBoundaryPath(long native_region,
418                                                         long native_path);
419
420     private static native boolean nativeOp(long native_dst, int left, int top,
421                                            int right, int bottom, int op);
422     private static native boolean nativeOp(long native_dst, Rect rect,
423                                            long native_region, int op);
424     private static native boolean nativeOp(long native_dst, long native_region1,
425                                            long native_region2, int op);
426
427     private static native long nativeCreateFromParcel(Parcel p);
428     private static native boolean nativeWriteToParcel(long native_region,
429                                                       Parcel p);
430
431     private static native String nativeToString(long native_region);
432 }