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