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