150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich/* 250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Copyright (C) 2006 The Android Open Source Project 350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * 49875750593aae7c2a62f33c620809d49162393ebElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 59875750593aae7c2a62f33c620809d49162393ebElliott Hughes * you may not use this file except in compliance with the License. 69875750593aae7c2a62f33c620809d49162393ebElliott Hughes * You may obtain a copy of the License at 750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * 89875750593aae7c2a62f33c620809d49162393ebElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * 109875750593aae7c2a62f33c620809d49162393ebElliott Hughes * Unless required by applicable law or agreed to in writing, software 119875750593aae7c2a62f33c620809d49162393ebElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 129875750593aae7c2a62f33c620809d49162393ebElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139875750593aae7c2a62f33c620809d49162393ebElliott Hughes * See the License for the specific language governing permissions and 1450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * limitations under the License. 1550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 1650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 1750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichpackage android.graphics; 1850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 199875750593aae7c2a62f33c620809d49162393ebElliott Hughesimport android.os.Parcel; 209875750593aae7c2a62f33c620809d49162393ebElliott Hughesimport android.os.Parcelable; 2150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 2250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevichpublic class Region implements Parcelable { 2350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** 2450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * @hide 2550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 2650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public final int mNativeRegion; 2750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 2850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich // the native values for these must match up with the enum in SkRegion.h 2950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public enum Op { 3050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich DIFFERENCE(0), 3150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich INTERSECT(1), 3250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich UNION(2), 3350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich XOR(3), 3450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich REVERSE_DIFFERENCE(4), 3550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich REPLACE(5); 3650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 3750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich Op(int nativeInt) { 3850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich this.nativeInt = nativeInt; 3950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 4050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 4150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** 429875750593aae7c2a62f33c620809d49162393ebElliott Hughes * @hide 4350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 4450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public final int nativeInt; 4550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 4650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 4750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Create an empty region 4850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 4950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public Region() { 5050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich this(nativeConstructor()); 5150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 5250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 5350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Return a copy of the specified region 5450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 5550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public Region(Region region) { 5650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich this(nativeConstructor()); 5750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich nativeSetRegion(mNativeRegion, region.mNativeRegion); 5850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 5950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 6050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Return a region set to the specified rectangle 6150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 6250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public Region(Rect r) { 6350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich mNativeRegion = nativeConstructor(); 6450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom); 65e58a97b5d77b59fad1572ba3c0572c7434e8e503Thomas Tafertshofer } 6650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 6750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Return a region set to the specified rectangle 6850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 6950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public Region(int left, int top, int right, int bottom) { 7050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich mNativeRegion = nativeConstructor(); 7150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich nativeSetRect(mNativeRegion, left, top, right, bottom); 7250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 7350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 7450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Set the region to the empty region 7550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 7650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public void setEmpty() { 7750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich nativeSetRect(mNativeRegion, 0, 0, 0, 0); 7850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 7950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 8050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Set the region to the specified region. 8150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 829875750593aae7c2a62f33c620809d49162393ebElliott Hughes public boolean set(Region region) { 8350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich return nativeSetRegion(mNativeRegion, region.mNativeRegion); 8450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 85e58a97b5d77b59fad1572ba3c0572c7434e8e503Thomas Tafertshofer 8650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Set the region to the specified rectangle 879875750593aae7c2a62f33c620809d49162393ebElliott Hughes */ 88e58a97b5d77b59fad1572ba3c0572c7434e8e503Thomas Tafertshofer public boolean set(Rect r) { 8950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich return nativeSetRect(mNativeRegion, r.left, r.top, r.right, r.bottom); 9050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 9150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 9250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** Set the region to the specified rectangle 9350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 9450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public boolean set(int left, int top, int right, int bottom) { 9550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich return nativeSetRect(mNativeRegion, left, top, right, bottom); 9650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 9750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 9850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** 9950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Set the region to the area described by the path and clip. 10050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Return true if the resulting region is non-empty. This produces a region 10150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * that is identical to the pixels that would be drawn by the path 10250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * (with no antialiasing). 10350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 10450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public boolean setPath(Path path, Region clip) { 10550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich return nativeSetPath(mNativeRegion, path.ni(), clip.mNativeRegion); 10650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich } 1079875750593aae7c2a62f33c620809d49162393ebElliott Hughes 1089875750593aae7c2a62f33c620809d49162393ebElliott Hughes /** 10950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Return true if this region is empty 11050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 11150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public native boolean isEmpty(); 11250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 11350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** 11450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Return true if the region contains a single rectangle 11550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 11650d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public native boolean isRect(); 11750d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 11850d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** 11950d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Return true if the region contains more than one rectangle 12050d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich */ 12150d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich public native boolean isComplex(); 12250d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich 12350d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich /** 12450d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * Return a new Rect set to the bounds of the region. If the region is 12550d0b14689b0ae95ea7b66a8c2f7b955115812ddJack Palevich * empty, the Rect will be set to [0, 0, 0, 0] 126 */ 127 public Rect getBounds() { 128 Rect r = new Rect(); 129 nativeGetBounds(mNativeRegion, r); 130 return r; 131 } 132 133 /** 134 * Set the Rect to the bounds of the region. If the region is empty, the 135 * Rect will be set to [0, 0, 0, 0] 136 */ 137 public boolean getBounds(Rect r) { 138 if (r == null) { 139 throw new NullPointerException(); 140 } 141 return nativeGetBounds(mNativeRegion, r); 142 } 143 144 /** 145 * Return the boundary of the region as a new Path. If the region is empty, 146 * the path will also be empty. 147 */ 148 public Path getBoundaryPath() { 149 Path path = new Path(); 150 nativeGetBoundaryPath(mNativeRegion, path.ni()); 151 return path; 152 } 153 154 /** 155 * Set the path to the boundary of the region. If the region is empty, the 156 * path will also be empty. 157 */ 158 public boolean getBoundaryPath(Path path) { 159 return nativeGetBoundaryPath(mNativeRegion, path.ni()); 160 } 161 162 /** 163 * Return true if the region contains the specified point 164 */ 165 public native boolean contains(int x, int y); 166 167 /** 168 * Return true if the region is a single rectangle (not complex) and it 169 * contains the specified rectangle. Returning false is not a guarantee 170 * that the rectangle is not contained by this region, but return true is a 171 * guarantee that the rectangle is contained by this region. 172 */ 173 public boolean quickContains(Rect r) { 174 return quickContains(r.left, r.top, r.right, r.bottom); 175 } 176 177 /** 178 * Return true if the region is a single rectangle (not complex) and it 179 * contains the specified rectangle. Returning false is not a guarantee 180 * that the rectangle is not contained by this region, but return true is a 181 * guarantee that the rectangle is contained by this region. 182 */ 183 public native boolean quickContains(int left, int top, int right, 184 int bottom); 185 186 /** 187 * Return true if the region is empty, or if the specified rectangle does 188 * not intersect the region. Returning false is not a guarantee that they 189 * intersect, but returning true is a guarantee that they do not. 190 */ 191 public boolean quickReject(Rect r) { 192 return quickReject(r.left, r.top, r.right, r.bottom); 193 } 194 195 /** 196 * Return true if the region is empty, or if the specified rectangle does 197 * not intersect the region. Returning false is not a guarantee that they 198 * intersect, but returning true is a guarantee that they do not. 199 */ 200 public native boolean quickReject(int left, int top, int right, int bottom); 201 202 /** 203 * Return true if the region is empty, or if the specified region does not 204 * intersect the region. Returning false is not a guarantee that they 205 * intersect, but returning true is a guarantee that they do not. 206 */ 207 public native boolean quickReject(Region rgn); 208 209 /** 210 * Translate the region by [dx, dy]. If the region is empty, do nothing. 211 */ 212 public void translate(int dx, int dy) { 213 translate(dx, dy, null); 214 } 215 216 /** 217 * Set the dst region to the result of translating this region by [dx, dy]. 218 * If this region is empty, then dst will be set to empty. 219 */ 220 public native void translate(int dx, int dy, Region dst); 221 222 /** 223 * Scale the region by the given scale amount. This re-constructs new region by 224 * scaling the rects that this region consists of. New rectis are computed by scaling 225 * coordinates by float, then rounded by roundf() function to integers. This may results 226 * in less internal rects if 0 < scale < 1. Zero and Negative scale result in 227 * an empty region. If this region is empty, do nothing. 228 * 229 * @hide 230 */ 231 public void scale(float scale) { 232 scale(scale, null); 233 } 234 235 /** 236 * Set the dst region to the result of scaling this region by the given scale amount. 237 * If this region is empty, then dst will be set to empty. 238 * @hide 239 */ 240 public native void scale(float scale, Region dst); 241 242 public final boolean union(Rect r) { 243 return op(r, Op.UNION); 244 } 245 246 /** 247 * Perform the specified Op on this region and the specified rect. Return 248 * true if the result of the op is not empty. 249 */ 250 public boolean op(Rect r, Op op) { 251 return nativeOp(mNativeRegion, r.left, r.top, r.right, r.bottom, 252 op.nativeInt); 253 } 254 255 /** 256 * Perform the specified Op on this region and the specified rect. Return 257 * true if the result of the op is not empty. 258 */ 259 public boolean op(int left, int top, int right, int bottom, Op op) { 260 return nativeOp(mNativeRegion, left, top, right, bottom, 261 op.nativeInt); 262 } 263 264 /** 265 * Perform the specified Op on this region and the specified region. Return 266 * true if the result of the op is not empty. 267 */ 268 public boolean op(Region region, Op op) { 269 return op(this, region, op); 270 } 271 272 /** 273 * Set this region to the result of performing the Op on the specified rect 274 * and region. Return true if the result is not empty. 275 */ 276 public boolean op(Rect rect, Region region, Op op) { 277 return nativeOp(mNativeRegion, rect, region.mNativeRegion, 278 op.nativeInt); 279 } 280 281 /** 282 * Set this region to the result of performing the Op on the specified 283 * regions. Return true if the result is not empty. 284 */ 285 public boolean op(Region region1, Region region2, Op op) { 286 return nativeOp(mNativeRegion, region1.mNativeRegion, 287 region2.mNativeRegion, op.nativeInt); 288 } 289 290 public String toString() { 291 return nativeToString(mNativeRegion); 292 } 293 294 ////////////////////////////////////////////////////////////////////////// 295 296 public static final Parcelable.Creator<Region> CREATOR 297 = new Parcelable.Creator<Region>() { 298 /** 299 * Rebuild a Region previously stored with writeToParcel(). 300 * @param p Parcel object to read the region from 301 * @return a new region created from the data in the parcel 302 */ 303 public Region createFromParcel(Parcel p) { 304 int ni = nativeCreateFromParcel(p); 305 if (ni == 0) { 306 throw new RuntimeException(); 307 } 308 return new Region(ni); 309 } 310 public Region[] newArray(int size) { 311 return new Region[size]; 312 } 313 }; 314 315 public int describeContents() { 316 return 0; 317 } 318 319 /** 320 * Write the region and its pixels to the parcel. The region can be 321 * rebuilt from the parcel by calling CREATOR.createFromParcel(). 322 * @param p Parcel object to write the region data into 323 */ 324 public void writeToParcel(Parcel p, int flags) { 325 if (!nativeWriteToParcel(mNativeRegion, p)) { 326 throw new RuntimeException(); 327 } 328 } 329 330 @Override 331 public boolean equals(Object obj) { 332 if (obj == null || !(obj instanceof Region)) { 333 return false; 334 } 335 Region peer = (Region) obj; 336 return nativeEquals(mNativeRegion, peer.mNativeRegion); 337 } 338 339 protected void finalize() throws Throwable { 340 try { 341 nativeDestructor(mNativeRegion); 342 } finally { 343 super.finalize(); 344 } 345 } 346 347 Region(int ni) { 348 if (ni == 0) { 349 throw new RuntimeException(); 350 } 351 mNativeRegion = ni; 352 } 353 354 /* add dummy parameter so constructor can be called from jni without 355 triggering 'not cloneable' exception */ 356 private Region(int ni, int dummy) { 357 this(ni); 358 } 359 360 final int ni() { 361 return mNativeRegion; 362 } 363 364 private static native boolean nativeEquals(int native_r1, int native_r2); 365 366 private static native int nativeConstructor(); 367 private static native void nativeDestructor(int native_region); 368 369 private static native boolean nativeSetRegion(int native_dst, 370 int native_src); 371 private static native boolean nativeSetRect(int native_dst, int left, 372 int top, int right, int bottom); 373 private static native boolean nativeSetPath(int native_dst, int native_path, 374 int native_clip); 375 private static native boolean nativeGetBounds(int native_region, Rect rect); 376 private static native boolean nativeGetBoundaryPath(int native_region, 377 int native_path); 378 379 private static native boolean nativeOp(int native_dst, int left, int top, 380 int right, int bottom, int op); 381 private static native boolean nativeOp(int native_dst, Rect rect, 382 int native_region, int op); 383 private static native boolean nativeOp(int native_dst, int native_region1, 384 int native_region2, int op); 385 386 private static native int nativeCreateFromParcel(Parcel p); 387 private static native boolean nativeWriteToParcel(int native_region, 388 Parcel p); 389 390 private static native String nativeToString(int native_region); 391} 392