Region.cpp revision 7c1a49f5f5ed6613d736464bf5001b777e89ced2
1/* 2 * Copyright (C) 2011 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#include "SkRegion.h" 18#include "SkPath.h" 19#include "GraphicsJNI.h" 20 21#include <binder/Parcel.h> 22#include "android_os_Parcel.h" 23#include "android_util_Binder.h" 24 25#include <jni.h> 26#include <android_runtime/AndroidRuntime.h> 27 28namespace android { 29 30static jfieldID gRegion_nativeInstanceFieldID; 31 32static inline SkRegion* GetSkRegion(JNIEnv* env, jobject regionObject) { 33 SkRegion* rgn = (SkRegion*)env->GetIntField(regionObject, gRegion_nativeInstanceFieldID); 34 SkASSERT(rgn != NULL); 35 return rgn; 36} 37 38static SkRegion* Region_constructor(JNIEnv* env, jobject) { 39 return new SkRegion; 40} 41 42static void Region_destructor(JNIEnv* env, jobject, SkRegion* region) { 43 SkASSERT(region); 44 delete region; 45} 46 47static void Region_setRegion(JNIEnv* env, jobject, SkRegion* dst, const SkRegion* src) { 48 SkASSERT(dst && src); 49 *dst = *src; 50} 51 52static jboolean Region_setRect(JNIEnv* env, jobject, SkRegion* dst, int left, int top, int right, int bottom) { 53 return dst->setRect(left, top, right, bottom); 54} 55 56static jboolean Region_setPath(JNIEnv* env, jobject, SkRegion* dst, 57 const SkPath* path, const SkRegion* clip) { 58 SkASSERT(dst && path && clip); 59 return dst->setPath(*path, *clip); 60} 61 62static jboolean Region_getBounds(JNIEnv* env, jobject, SkRegion* region, jobject rectBounds) { 63 GraphicsJNI::irect_to_jrect(region->getBounds(), env, rectBounds); 64 return !region->isEmpty(); 65} 66 67static jboolean Region_getBoundaryPath(JNIEnv* env, jobject, const SkRegion* region, SkPath* path) { 68 return region->getBoundaryPath(path); 69} 70 71static jboolean Region_op0(JNIEnv* env, jobject, SkRegion* dst, int left, int top, int right, int bottom, int op) { 72 SkIRect ir; 73 74 ir.set(left, top, right, bottom); 75 return dst->op(ir, (SkRegion::Op)op); 76} 77 78static jboolean Region_op1(JNIEnv* env, jobject, SkRegion* dst, jobject rectObject, const SkRegion* region, int op) { 79 SkIRect ir; 80 GraphicsJNI::jrect_to_irect(env, rectObject, &ir); 81 return dst->op(ir, *region, (SkRegion::Op)op); 82} 83 84static jboolean Region_op2(JNIEnv* env, jobject, SkRegion* dst, const SkRegion* region1, const SkRegion* region2, int op) { 85 return dst->op(*region1, *region2, (SkRegion::Op)op); 86} 87 88//////////////////////////////////// These are methods, not static 89 90static jboolean Region_isEmpty(JNIEnv* env, jobject region) { 91 return GetSkRegion(env, region)->isEmpty(); 92} 93 94static jboolean Region_isRect(JNIEnv* env, jobject region) { 95 return GetSkRegion(env, region)->isRect(); 96} 97 98static jboolean Region_isComplex(JNIEnv* env, jobject region) { 99 return GetSkRegion(env, region)->isComplex(); 100} 101 102static jboolean Region_contains(JNIEnv* env, jobject region, int x, int y) { 103 return GetSkRegion(env, region)->contains(x, y); 104} 105 106static jboolean Region_quickContains(JNIEnv* env, jobject region, int left, int top, int right, int bottom) { 107 return GetSkRegion(env, region)->quickContains(left, top, right, bottom); 108} 109 110static jboolean Region_quickRejectIIII(JNIEnv* env, jobject region, int left, int top, int right, int bottom) { 111 SkIRect ir; 112 ir.set(left, top, right, bottom); 113 return GetSkRegion(env, region)->quickReject(ir); 114} 115 116static jboolean Region_quickRejectRgn(JNIEnv* env, jobject region, jobject other) { 117 return GetSkRegion(env, region)->quickReject(*GetSkRegion(env, other)); 118} 119 120static void Region_translate(JNIEnv* env, jobject region, int x, int y, jobject dst) { 121 SkRegion* rgn = GetSkRegion(env, region); 122 if (dst) 123 rgn->translate(x, y, GetSkRegion(env, dst)); 124 else 125 rgn->translate(x, y); 126} 127 128// Scale the rectangle by given scale and set the reuslt to the dst. 129static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) { 130 dst->fLeft = (int)::roundf(src.fLeft * scale); 131 dst->fTop = (int)::roundf(src.fTop * scale); 132 dst->fRight = (int)::roundf(src.fRight * scale); 133 dst->fBottom = (int)::roundf(src.fBottom * scale); 134} 135 136// Scale the region by given scale and set the reuslt to the dst. 137// dest and src can be the same region instance. 138static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) { 139 SkRegion tmp; 140 SkRegion::Iterator iter(src); 141 142 for (; !iter.done(); iter.next()) { 143 SkIRect r; 144 scale_rect(&r, iter.rect(), scale); 145 tmp.op(r, SkRegion::kUnion_Op); 146 } 147 dst->swap(tmp); 148} 149 150static void Region_scale(JNIEnv* env, jobject region, jfloat scale, jobject dst) { 151 SkRegion* rgn = GetSkRegion(env, region); 152 if (dst) 153 scale_rgn(GetSkRegion(env, dst), *rgn, scale); 154 else 155 scale_rgn(rgn, *rgn, scale); 156} 157 158static jstring Region_toString(JNIEnv* env, jobject clazz, SkRegion* region) { 159 char* str = region->toString(); 160 if (str == NULL) { 161 return NULL; 162 } 163 jstring result = env->NewStringUTF(str); 164 free(str); 165 return result; 166} 167 168//////////////////////////////////////////////////////////////////////////////////////////////////////////// 169 170static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel) 171{ 172 if (parcel == NULL) { 173 return NULL; 174 } 175 176 android::Parcel* p = android::parcelForJavaObject(env, parcel); 177 178 SkRegion* region = new SkRegion; 179 size_t size = p->readInt32(); 180 region->unflatten(p->readInplace(size)); 181 182 return region; 183} 184 185static jboolean Region_writeToParcel(JNIEnv* env, jobject clazz, const SkRegion* region, jobject parcel) 186{ 187 if (parcel == NULL) { 188 return false; 189 } 190 191 android::Parcel* p = android::parcelForJavaObject(env, parcel); 192 193 size_t size = region->flatten(NULL); 194 p->writeInt32(size); 195 region->flatten(p->writeInplace(size)); 196 197 return true; 198} 199 200//////////////////////////////////////////////////////////////////////////////////////////////////////////// 201 202static jboolean Region_equals(JNIEnv* env, jobject clazz, const SkRegion *r1, const SkRegion* r2) 203{ 204 return (jboolean) (*r1 == *r2); 205} 206 207//////////////////////////////////////////////////////////////////////////////////////////////////////////// 208 209struct RgnIterPair { 210 SkRegion fRgn; // a copy of the caller's region 211 SkRegion::Iterator fIter; // an iterator acting upon the copy (fRgn) 212 213 RgnIterPair(const SkRegion& rgn) : fRgn(rgn) { 214 // have our iterator reference our copy (fRgn), so we know it will be 215 // unchanged for the lifetime of the iterator 216 fIter.reset(fRgn); 217 } 218}; 219 220static RgnIterPair* RegionIter_constructor(JNIEnv* env, jobject, const SkRegion* region) 221{ 222 SkASSERT(region); 223 return new RgnIterPair(*region); 224} 225 226static void RegionIter_destructor(JNIEnv* env, jobject, RgnIterPair* pair) 227{ 228 SkASSERT(pair); 229 delete pair; 230} 231 232static jboolean RegionIter_next(JNIEnv* env, jobject, RgnIterPair* pair, jobject rectObject) 233{ 234 // the caller has checked that rectObject is not nul 235 SkASSERT(pair); 236 SkASSERT(rectObject); 237 238 if (!pair->fIter.done()) { 239 GraphicsJNI::irect_to_jrect(pair->fIter.rect(), env, rectObject); 240 pair->fIter.next(); 241 return true; 242 } 243 return false; 244} 245 246//////////////////////////////////////////////////////////////////////////////////////////////////////////// 247 248static JNINativeMethod gRegionIterMethods[] = { 249 { "nativeConstructor", "(I)I", (void*)RegionIter_constructor }, 250 { "nativeDestructor", "(I)V", (void*)RegionIter_destructor }, 251 { "nativeNext", "(ILandroid/graphics/Rect;)Z", (void*)RegionIter_next } 252}; 253 254static JNINativeMethod gRegionMethods[] = { 255 // these are static methods 256 { "nativeConstructor", "()I", (void*)Region_constructor }, 257 { "nativeDestructor", "(I)V", (void*)Region_destructor }, 258 { "nativeSetRegion", "(II)V", (void*)Region_setRegion }, 259 { "nativeSetRect", "(IIIII)Z", (void*)Region_setRect }, 260 { "nativeSetPath", "(III)Z", (void*)Region_setPath }, 261 { "nativeGetBounds", "(ILandroid/graphics/Rect;)Z", (void*)Region_getBounds }, 262 { "nativeGetBoundaryPath", "(II)Z", (void*)Region_getBoundaryPath }, 263 { "nativeOp", "(IIIIII)Z", (void*)Region_op0 }, 264 { "nativeOp", "(ILandroid/graphics/Rect;II)Z", (void*)Region_op1 }, 265 { "nativeOp", "(IIII)Z", (void*)Region_op2 }, 266 // these are methods that take the java region object 267 { "isEmpty", "()Z", (void*)Region_isEmpty }, 268 { "isRect", "()Z", (void*)Region_isRect }, 269 { "isComplex", "()Z", (void*)Region_isComplex }, 270 { "contains", "(II)Z", (void*)Region_contains }, 271 { "quickContains", "(IIII)Z", (void*)Region_quickContains }, 272 { "quickReject", "(IIII)Z", (void*)Region_quickRejectIIII }, 273 { "quickReject", "(Landroid/graphics/Region;)Z", (void*)Region_quickRejectRgn }, 274 { "scale", "(FLandroid/graphics/Region;)V", (void*)Region_scale }, 275 { "translate", "(IILandroid/graphics/Region;)V", (void*)Region_translate }, 276 { "nativeToString", "(I)Ljava/lang/String;", (void*)Region_toString }, 277 // parceling methods 278 { "nativeCreateFromParcel", "(Landroid/os/Parcel;)I", (void*)Region_createFromParcel }, 279 { "nativeWriteToParcel", "(ILandroid/os/Parcel;)Z", (void*)Region_writeToParcel }, 280 { "nativeEquals", "(II)Z", (void*)Region_equals }, 281}; 282 283int register_android_graphics_Region(JNIEnv* env) 284{ 285 jclass clazz = env->FindClass("android/graphics/Region"); 286 SkASSERT(clazz); 287 288 gRegion_nativeInstanceFieldID = env->GetFieldID(clazz, "mNativeRegion", "I"); 289 SkASSERT(gRegion_nativeInstanceFieldID); 290 291 int result = android::AndroidRuntime::registerNativeMethods(env, "android/graphics/Region", 292 gRegionMethods, SK_ARRAY_COUNT(gRegionMethods)); 293 if (result < 0) 294 return result; 295 296 return android::AndroidRuntime::registerNativeMethods(env, "android/graphics/RegionIterator", 297 gRegionIterMethods, SK_ARRAY_COUNT(gRegionIterMethods)); 298} 299 300SkRegion* android_graphics_Region_getSkRegion(JNIEnv* env, jobject regionObj) { 301 return GetSkRegion(env, regionObj); 302} 303 304} // namespace android 305