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