2 * Copyright (C) 2006 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package android.graphics;
19 import android.os.Parcel;
20 import android.os.Parcelable;
21 import android.util.Pools.SynchronizedPool;
23 public class Region implements Parcelable {
25 private static final int MAX_POOL_SIZE = 10;
27 private static final SynchronizedPool<Region> sPool =
28 new SynchronizedPool<Region>(MAX_POOL_SIZE);
33 public long mNativeRegion;
35 // the native values for these must match up with the enum in SkRegion.h
41 REVERSE_DIFFERENCE(4),
45 this.nativeInt = nativeInt;
51 public final int nativeInt;
54 /** Create an empty region
57 this(nativeConstructor());
60 /** Return a copy of the specified region
62 public Region(Region region) {
63 this(nativeConstructor());
64 nativeSetRegion(mNativeRegion, region.mNativeRegion);
67 /** Return a region set to the specified rectangle
69 public Region(Rect r) {
70 mNativeRegion = nativeConstructor();
71 nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
74 /** Return a region set to the specified rectangle
76 public Region(int left, int top, int right, int bottom) {
77 mNativeRegion = nativeConstructor();
78 nativeSetRect(mNativeRegion, left, top, right, bottom);
81 /** Set the region to the empty region
83 public void setEmpty() {
84 nativeSetRect(mNativeRegion, 0, 0, 0, 0);
87 /** Set the region to the specified region.
89 public boolean set(Region region) {
90 nativeSetRegion(mNativeRegion, region.mNativeRegion);
94 /** Set the region to the specified rectangle
96 public boolean set(Rect r) {
97 return nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom);
100 /** Set the region to the specified rectangle
102 public boolean set(int left, int top, int right, int bottom) {
103 return nativeSetRect(mNativeRegion, left, top, right, bottom);
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).
112 public boolean setPath(Path path, Region clip) {
113 return nativeSetPath(mNativeRegion, path.readOnlyNI(), clip.mNativeRegion);
117 * Return true if this region is empty
119 public native boolean isEmpty();
122 * Return true if the region contains a single rectangle
124 public native boolean isRect();
127 * Return true if the region contains more than one rectangle
129 public native boolean isComplex();
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]
135 public Rect getBounds() {
137 nativeGetBounds(mNativeRegion, r);
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]
145 public boolean getBounds(Rect r) {
147 throw new NullPointerException();
149 return nativeGetBounds(mNativeRegion, r);
153 * Return the boundary of the region as a new Path. If the region is empty,
154 * the path will also be empty.
156 public Path getBoundaryPath() {
157 Path path = new Path();
158 nativeGetBoundaryPath(mNativeRegion, path.mutateNI());
163 * Set the path to the boundary of the region. If the region is empty, the
164 * path will also be empty.
166 public boolean getBoundaryPath(Path path) {
167 return nativeGetBoundaryPath(mNativeRegion, path.mutateNI());
171 * Return true if the region contains the specified point
173 public native boolean contains(int x, int y);
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.
181 public boolean quickContains(Rect r) {
182 return quickContains(r.left, r.top, r.right, r.bottom);
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.
191 public native boolean quickContains(int left, int top, int right,
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.
199 public boolean quickReject(Rect r) {
200 return quickReject(r.left, r.top, r.right, r.bottom);
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.
208 public native boolean quickReject(int left, int top, int right, int bottom);
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.
215 public native boolean quickReject(Region rgn);
218 * Translate the region by [dx, dy]. If the region is empty, do nothing.
220 public void translate(int dx, int dy) {
221 translate(dx, dy, null);
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.
228 public native void translate(int dx, int dy, Region dst);
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.
239 public void scale(float scale) {
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.
248 public native void scale(float scale, Region dst);
250 public final boolean union(Rect r) {
251 return op(r, Op.UNION);
255 * Perform the specified Op on this region and the specified rect. Return
256 * true if the result of the op is not empty.
258 public boolean op(Rect r, Op op) {
259 return nativeOp(mNativeRegion, r.left, r.top, r.right, r.bottom,
264 * Perform the specified Op on this region and the specified rect. Return
265 * true if the result of the op is not empty.
267 public boolean op(int left, int top, int right, int bottom, Op op) {
268 return nativeOp(mNativeRegion, left, top, right, bottom,
273 * Perform the specified Op on this region and the specified region. Return
274 * true if the result of the op is not empty.
276 public boolean op(Region region, Op op) {
277 return op(this, region, op);
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.
284 public boolean op(Rect rect, Region region, Op op) {
285 return nativeOp(mNativeRegion, rect, region.mNativeRegion,
290 * Set this region to the result of performing the Op on the specified
291 * regions. Return true if the result is not empty.
293 public boolean op(Region region1, Region region2, Op op) {
294 return nativeOp(mNativeRegion, region1.mNativeRegion,
295 region2.mNativeRegion, op.nativeInt);
298 public String toString() {
299 return nativeToString(mNativeRegion);
303 * @return An instance from a pool if such or a new one.
307 public static Region obtain() {
308 Region region = sPool.acquire();
309 return (region != null) ? region : new Region();
313 * @return An instance from a pool if such or a new one.
315 * @param other Region to copy values from for initialization.
319 public static Region obtain(Region other) {
320 Region region = obtain();
326 * Recycles an instance.
330 public void recycle() {
335 //////////////////////////////////////////////////////////////////////////
337 public static final Parcelable.Creator<Region> CREATOR
338 = new Parcelable.Creator<Region>() {
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
344 public Region createFromParcel(Parcel p) {
345 long ni = nativeCreateFromParcel(p);
347 throw new RuntimeException();
349 return new Region(ni);
351 public Region[] newArray(int size) {
352 return new Region[size];
356 public int describeContents() {
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
365 public void writeToParcel(Parcel p, int flags) {
366 if (!nativeWriteToParcel(mNativeRegion, p)) {
367 throw new RuntimeException();
372 public boolean equals(Object obj) {
373 if (obj == null || !(obj instanceof Region)) {
376 Region peer = (Region) obj;
377 return nativeEquals(mNativeRegion, peer.mNativeRegion);
380 protected void finalize() throws Throwable {
382 nativeDestructor(mNativeRegion);
391 throw new RuntimeException();
396 /* add dummy parameter so constructor can be called from jni without
397 triggering 'not cloneable' exception */
398 private Region(long ni, int dummy) {
403 return mNativeRegion;
406 private static native boolean nativeEquals(long native_r1, long native_r2);
408 private static native long nativeConstructor();
409 private static native void nativeDestructor(long native_region);
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,
416 private static native boolean nativeGetBounds(long native_region, Rect rect);
417 private static native boolean nativeGetBoundaryPath(long native_region,
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);
427 private static native long nativeCreateFromParcel(Parcel p);
428 private static native boolean nativeWriteToParcel(long native_region,
431 private static native String nativeToString(long native_region);