Graphics.cpp revision 2118b25ad422e946d4d87e191c5710bfacd7503e
1#define LOG_TAG "GraphicsJNI" 2 3#include "jni.h" 4#include "GraphicsJNI.h" 5 6#include "SkCanvas.h" 7#include "SkDevice.h" 8#include "SkPicture.h" 9#include "SkRegion.h" 10#include <android_runtime/AndroidRuntime.h> 11 12void doThrow(JNIEnv* env, const char* exc, const char* msg) { 13 // don't throw a new exception if we already have one pending 14 if (env->ExceptionCheck() == JNI_FALSE) { 15 jclass npeClazz; 16 17 npeClazz = env->FindClass(exc); 18 LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc); 19 20 env->ThrowNew(npeClazz, msg); 21 } 22} 23 24void doThrowNPE(JNIEnv* env) { 25 doThrow(env, "java/lang/NullPointerException"); 26} 27 28void doThrowAIOOBE(JNIEnv* env) { 29 doThrow(env, "java/lang/ArrayIndexOutOfBoundsException"); 30} 31 32void doThrowRE(JNIEnv* env, const char* msg) { 33 doThrow(env, "java/lang/RuntimeException", msg); 34} 35 36void doThrowIAE(JNIEnv* env, const char* msg) { 37 doThrow(env, "java/lang/IllegalArgumentException", msg); 38} 39 40void doThrowISE(JNIEnv* env, const char* msg) { 41 doThrow(env, "java/lang/IllegalStateException", msg); 42} 43 44void doThrowOOME(JNIEnv* env, const char* msg) { 45 doThrow(env, "java/lang/OutOfMemoryError", msg); 46} 47 48void doThrowIOE(JNIEnv* env, const char* msg) { 49 doThrow(env, "java/io/IOException", msg); 50} 51 52bool GraphicsJNI::hasException(JNIEnv *env) { 53 if (env->ExceptionCheck() != 0) { 54 LOGE("*** Uncaught exception returned from Java call!\n"); 55 env->ExceptionDescribe(); 56 return true; 57 } 58 return false; 59} 60 61/////////////////////////////////////////////////////////////////////////////// 62 63AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array, 64 int minLength, JNIAccess access) 65: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 66 SkASSERT(env); 67 if (array) { 68 fLen = env->GetArrayLength(array); 69 if (fLen < minLength) { 70 sk_throw(); 71 } 72 fPtr = env->GetFloatArrayElements(array, NULL); 73 } 74 fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; 75} 76 77AutoJavaFloatArray::~AutoJavaFloatArray() { 78 if (fPtr) { 79 fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode); 80 } 81} 82 83AutoJavaIntArray::AutoJavaIntArray(JNIEnv* env, jintArray array, 84 int minLength) 85: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 86 SkASSERT(env); 87 if (array) { 88 fLen = env->GetArrayLength(array); 89 if (fLen < minLength) { 90 sk_throw(); 91 } 92 fPtr = env->GetIntArrayElements(array, NULL); 93 } 94} 95 96AutoJavaIntArray::~AutoJavaIntArray() { 97 if (fPtr) { 98 fEnv->ReleaseIntArrayElements(fArray, fPtr, 0); 99 } 100} 101 102AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array, 103 int minLength, JNIAccess access) 104: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 105 SkASSERT(env); 106 if (array) { 107 fLen = env->GetArrayLength(array); 108 if (fLen < minLength) { 109 sk_throw(); 110 } 111 fPtr = env->GetShortArrayElements(array, NULL); 112 } 113 fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0; 114} 115 116AutoJavaShortArray::~AutoJavaShortArray() { 117 if (fPtr) { 118 fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode); 119 } 120} 121 122AutoJavaByteArray::AutoJavaByteArray(JNIEnv* env, jbyteArray array, 123 int minLength) 124: fEnv(env), fArray(array), fPtr(NULL), fLen(0) { 125 SkASSERT(env); 126 if (array) { 127 fLen = env->GetArrayLength(array); 128 if (fLen < minLength) { 129 sk_throw(); 130 } 131 fPtr = env->GetByteArrayElements(array, NULL); 132 } 133} 134 135AutoJavaByteArray::~AutoJavaByteArray() { 136 if (fPtr) { 137 fEnv->ReleaseByteArrayElements(fArray, fPtr, 0); 138 } 139} 140 141/////////////////////////////////////////////////////////////////////////////// 142 143static jclass gRect_class; 144static jfieldID gRect_leftFieldID; 145static jfieldID gRect_topFieldID; 146static jfieldID gRect_rightFieldID; 147static jfieldID gRect_bottomFieldID; 148 149static jclass gRectF_class; 150static jfieldID gRectF_leftFieldID; 151static jfieldID gRectF_topFieldID; 152static jfieldID gRectF_rightFieldID; 153static jfieldID gRectF_bottomFieldID; 154 155static jclass gPoint_class; 156static jfieldID gPoint_xFieldID; 157static jfieldID gPoint_yFieldID; 158 159static jclass gPointF_class; 160static jfieldID gPointF_xFieldID; 161static jfieldID gPointF_yFieldID; 162 163static jclass gBitmap_class; 164static jfieldID gBitmap_nativeInstanceID; 165static jmethodID gBitmap_constructorMethodID; 166 167static jclass gBitmapConfig_class; 168static jfieldID gBitmapConfig_nativeInstanceID; 169 170static jclass gBitmapRegionDecoder_class; 171static jmethodID gBitmapRegionDecoder_constructorMethodID; 172 173static jclass gCanvas_class; 174static jfieldID gCanvas_nativeInstanceID; 175 176static jclass gPaint_class; 177static jfieldID gPaint_nativeInstanceID; 178 179static jclass gPicture_class; 180static jfieldID gPicture_nativeInstanceID; 181 182static jclass gRegion_class; 183static jfieldID gRegion_nativeInstanceID; 184static jmethodID gRegion_constructorMethodID; 185 186/////////////////////////////////////////////////////////////////////////////// 187 188void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B) 189{ 190 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 191 192 *L = env->GetIntField(obj, gRect_leftFieldID); 193 *T = env->GetIntField(obj, gRect_topFieldID); 194 *R = env->GetIntField(obj, gRect_rightFieldID); 195 *B = env->GetIntField(obj, gRect_bottomFieldID); 196} 197 198void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B) 199{ 200 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 201 202 env->SetIntField(obj, gRect_leftFieldID, L); 203 env->SetIntField(obj, gRect_topFieldID, T); 204 env->SetIntField(obj, gRect_rightFieldID, R); 205 env->SetIntField(obj, gRect_bottomFieldID, B); 206} 207 208SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir) 209{ 210 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 211 212 ir->set(env->GetIntField(obj, gRect_leftFieldID), 213 env->GetIntField(obj, gRect_topFieldID), 214 env->GetIntField(obj, gRect_rightFieldID), 215 env->GetIntField(obj, gRect_bottomFieldID)); 216 return ir; 217} 218 219void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj) 220{ 221 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 222 223 env->SetIntField(obj, gRect_leftFieldID, ir.fLeft); 224 env->SetIntField(obj, gRect_topFieldID, ir.fTop); 225 env->SetIntField(obj, gRect_rightFieldID, ir.fRight); 226 env->SetIntField(obj, gRect_bottomFieldID, ir.fBottom); 227} 228 229SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r) 230{ 231 SkASSERT(env->IsInstanceOf(obj, gRectF_class)); 232 233 r->set(SkFloatToScalar(env->GetFloatField(obj, gRectF_leftFieldID)), 234 SkFloatToScalar(env->GetFloatField(obj, gRectF_topFieldID)), 235 SkFloatToScalar(env->GetFloatField(obj, gRectF_rightFieldID)), 236 SkFloatToScalar(env->GetFloatField(obj, gRectF_bottomFieldID))); 237 return r; 238} 239 240SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r) 241{ 242 SkASSERT(env->IsInstanceOf(obj, gRect_class)); 243 244 r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)), 245 SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)), 246 SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)), 247 SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID))); 248 return r; 249} 250 251void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj) 252{ 253 SkASSERT(env->IsInstanceOf(obj, gRectF_class)); 254 255 env->SetFloatField(obj, gRectF_leftFieldID, SkScalarToFloat(r.fLeft)); 256 env->SetFloatField(obj, gRectF_topFieldID, SkScalarToFloat(r.fTop)); 257 env->SetFloatField(obj, gRectF_rightFieldID, SkScalarToFloat(r.fRight)); 258 env->SetFloatField(obj, gRectF_bottomFieldID, SkScalarToFloat(r.fBottom)); 259} 260 261SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* point) 262{ 263 SkASSERT(env->IsInstanceOf(obj, gPoint_class)); 264 265 point->set(env->GetIntField(obj, gPoint_xFieldID), 266 env->GetIntField(obj, gPoint_yFieldID)); 267 return point; 268} 269 270void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj) 271{ 272 SkASSERT(env->IsInstanceOf(obj, gPoint_class)); 273 274 env->SetIntField(obj, gPoint_xFieldID, ir.fX); 275 env->SetIntField(obj, gPoint_yFieldID, ir.fY); 276} 277 278SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point) 279{ 280 SkASSERT(env->IsInstanceOf(obj, gPointF_class)); 281 282 point->set(SkFloatToScalar(env->GetIntField(obj, gPointF_xFieldID)), 283 SkFloatToScalar(env->GetIntField(obj, gPointF_yFieldID))); 284 return point; 285} 286 287void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj) 288{ 289 SkASSERT(env->IsInstanceOf(obj, gPointF_class)); 290 291 env->SetFloatField(obj, gPointF_xFieldID, SkScalarToFloat(r.fX)); 292 env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY)); 293} 294 295SkBitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) { 296 SkASSERT(env); 297 SkASSERT(bitmap); 298 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); 299 SkBitmap* b = (SkBitmap*)env->GetIntField(bitmap, gBitmap_nativeInstanceID); 300 SkASSERT(b); 301 return b; 302} 303 304SkBitmap::Config GraphicsJNI::getNativeBitmapConfig(JNIEnv* env, 305 jobject jconfig) { 306 SkASSERT(env); 307 if (NULL == jconfig) { 308 return SkBitmap::kNo_Config; 309 } 310 SkASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class)); 311 int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID); 312 if (c < 0 || c >= SkBitmap::kConfigCount) { 313 c = SkBitmap::kNo_Config; 314 } 315 return static_cast<SkBitmap::Config>(c); 316} 317 318SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) { 319 SkASSERT(env); 320 SkASSERT(canvas); 321 SkASSERT(env->IsInstanceOf(canvas, gCanvas_class)); 322 SkCanvas* c = (SkCanvas*)env->GetIntField(canvas, gCanvas_nativeInstanceID); 323 SkASSERT(c); 324 return c; 325} 326 327SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) { 328 SkASSERT(env); 329 SkASSERT(paint); 330 SkASSERT(env->IsInstanceOf(paint, gPaint_class)); 331 SkPaint* p = (SkPaint*)env->GetIntField(paint, gPaint_nativeInstanceID); 332 SkASSERT(p); 333 return p; 334} 335 336SkPicture* GraphicsJNI::getNativePicture(JNIEnv* env, jobject picture) 337{ 338 SkASSERT(env); 339 SkASSERT(picture); 340 SkASSERT(env->IsInstanceOf(picture, gPicture_class)); 341 SkPicture* p = (SkPicture*)env->GetIntField(picture, gPicture_nativeInstanceID); 342 SkASSERT(p); 343 return p; 344} 345 346SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) 347{ 348 SkASSERT(env); 349 SkASSERT(region); 350 SkASSERT(env->IsInstanceOf(region, gRegion_class)); 351 SkRegion* r = (SkRegion*)env->GetIntField(region, gRegion_nativeInstanceID); 352 SkASSERT(r); 353 return r; 354} 355 356/////////////////////////////////////////////////////////////////////////////////////////// 357 358jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer, 359 bool isMutable, jbyteArray ninepatch, int density) 360{ 361 SkASSERT(bitmap); 362 SkASSERT(bitmap->pixelRef()); 363 364 jobject obj = env->AllocObject(gBitmap_class); 365 if (obj) { 366 env->CallVoidMethod(obj, gBitmap_constructorMethodID, 367 (jint)bitmap, buffer, isMutable, ninepatch, density); 368 if (hasException(env)) { 369 obj = NULL; 370 } 371 } 372 return obj; 373} 374 375jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, 376 jbyteArray ninepatch, int density) 377{ 378 return createBitmap(env, bitmap, NULL, isMutable, ninepatch, density); 379} 380 381 382jobject GraphicsJNI::createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap) 383{ 384 SkASSERT(bitmap != NULL); 385 386 jobject obj = env->AllocObject(gBitmapRegionDecoder_class); 387 if (hasException(env)) { 388 obj = NULL; 389 return obj; 390 } 391 if (obj) { 392 env->CallVoidMethod(obj, gBitmapRegionDecoder_constructorMethodID, (jint)bitmap); 393 if (hasException(env)) { 394 obj = NULL; 395 } 396 } 397 return obj; 398} 399 400jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region) 401{ 402 SkASSERT(region != NULL); 403 jobject obj = env->AllocObject(gRegion_class); 404 if (obj) { 405 env->CallVoidMethod(obj, gRegion_constructorMethodID, (jint)region, 0); 406 if (hasException(env)) { 407 obj = NULL; 408 } 409 } 410 return obj; 411} 412 413static JNIEnv* vm2env(JavaVM* vm) 414{ 415 JNIEnv* env = NULL; 416 if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env) 417 { 418 SkDebugf("------- [%p] vm->GetEnv() failed\n", vm); 419 sk_throw(); 420 } 421 return env; 422} 423 424/////////////////////////////////////////////////////////////////////////////// 425 426AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj, 427 SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable) { 428 SkASSERT(storage); 429 SkASSERT(env); 430 431 if (env->GetJavaVM(&fVM) != JNI_OK) { 432 SkDebugf("------ [%p] env->GetJavaVM failed\n", env); 433 sk_throw(); 434 } 435 fStorageObj = storageObj; 436 fHasGlobalRef = false; 437 fGlobalRefCnt = 0; 438 439 // If storageObj is NULL, the memory was NOT allocated on the Java heap 440 fOnJavaHeap = (storageObj != NULL); 441 442} 443 444AndroidPixelRef::~AndroidPixelRef() { 445 if (fOnJavaHeap) { 446 JNIEnv* env = vm2env(fVM); 447 448 if (fStorageObj && fHasGlobalRef) { 449 env->DeleteGlobalRef(fStorageObj); 450 } 451 fStorageObj = NULL; 452 453 // Set this to NULL to prevent the SkMallocPixelRef destructor 454 // from freeing the memory. 455 fStorage = NULL; 456 } 457} 458 459void AndroidPixelRef::setLocalJNIRef(jbyteArray arr) { 460 if (!fHasGlobalRef) { 461 fStorageObj = arr; 462 } 463} 464 465void AndroidPixelRef::globalRef(void* localref) { 466 if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) { 467 JNIEnv *env = vm2env(fVM); 468 469 // If JNI ref was passed, it is always used 470 if (localref) fStorageObj = (jbyteArray) localref; 471 472 if (fStorageObj == NULL) { 473 SkDebugf("No valid local ref to create a JNI global ref\n"); 474 sk_throw(); 475 } 476 if (fHasGlobalRef) { 477 // This should never happen 478 SkDebugf("Already holding a JNI global ref"); 479 sk_throw(); 480 } 481 482 fStorageObj = (jbyteArray) env->NewGlobalRef(fStorageObj); 483 // TODO: Check for failure here 484 fHasGlobalRef = true; 485 } 486 ref(); 487} 488 489void AndroidPixelRef::globalUnref() { 490 if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) { 491 JNIEnv *env = vm2env(fVM); 492 if (!fHasGlobalRef) { 493 SkDebugf("We don't have a global ref!"); 494 sk_throw(); 495 } 496 env->DeleteGlobalRef(fStorageObj); 497 fStorageObj = NULL; 498 fHasGlobalRef = false; 499 } 500 unref(); 501} 502 503/////////////////////////////////////////////////////////////////////////////// 504 505jbyteArray GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, 506 SkColorTable* ctable) { 507 Sk64 size64 = bitmap->getSize64(); 508 if (size64.isNeg() || !size64.is32()) { 509 doThrow(env, "java/lang/IllegalArgumentException", 510 "bitmap size exceeds 32bits"); 511 return NULL; 512 } 513 514 size_t size = size64.get32(); 515 jbyteArray arrayObj = env->NewByteArray(size); 516 if (arrayObj) { 517 jbyte *addr = env->GetByteArrayElements(arrayObj, NULL); 518 env->ReleaseByteArrayElements(arrayObj, addr, 0); 519 if (addr) { 520 SkPixelRef* pr = new AndroidPixelRef(env, (void*) addr, size, arrayObj, ctable); 521 bitmap->setPixelRef(pr)->unref(); 522 // since we're already allocated, we lockPixels right away 523 // HeapAllocator behaves this way too 524 bitmap->lockPixels(); 525 } 526 } 527 528 return arrayObj; 529} 530 531/////////////////////////////////////////////////////////////////////////////// 532 533JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) 534 : fStorageObj(NULL), 535 fAllocCount(0) { 536 if (env->GetJavaVM(&fVM) != JNI_OK) { 537 SkDebugf("------ [%p] env->GetJavaVM failed\n", env); 538 sk_throw(); 539 } 540} 541 542bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { 543 JNIEnv* env = vm2env(fVM); 544 545 // If allocating in the Java heap, only allow a single object to be 546 // allocated for the lifetime of this object. 547 if (fStorageObj != NULL) { 548 SkDebugf("WARNING: One-shot allocator has already allocated (alloc count = %d)\n", fAllocCount); 549// sk_throw(); 550 } 551 fStorageObj = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable); 552 fAllocCount += 1; 553 return fStorageObj != NULL; 554} 555 556//////////////////////////////////////////////////////////////////////////////// 557 558JavaHeapBitmapRef::JavaHeapBitmapRef(JNIEnv* env, SkBitmap* nativeBitmap, jbyteArray buffer) { 559 fEnv = env; 560 fNativeBitmap = nativeBitmap; 561 fBuffer = buffer; 562 563 // If the buffer is NULL, the backing memory wasn't allocated on the Java heap 564 if (fBuffer) { 565 ((AndroidPixelRef*) fNativeBitmap->pixelRef())->setLocalJNIRef(fBuffer); 566 } 567} 568 569JavaHeapBitmapRef::~JavaHeapBitmapRef() { 570 if (fBuffer) { 571 ((AndroidPixelRef*) fNativeBitmap->pixelRef())->setLocalJNIRef(NULL); 572 } 573} 574 575//////////////////////////////////////////////////////////////////////////////// 576 577static jclass make_globalref(JNIEnv* env, const char classname[]) 578{ 579 jclass c = env->FindClass(classname); 580 SkASSERT(c); 581 return (jclass)env->NewGlobalRef(c); 582} 583 584static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, 585 const char fieldname[], const char type[]) 586{ 587 jfieldID id = env->GetFieldID(clazz, fieldname, type); 588 SkASSERT(id); 589 return id; 590} 591 592int register_android_graphics_Graphics(JNIEnv* env) 593{ 594 jmethodID m; 595 jclass c; 596 597 gRect_class = make_globalref(env, "android/graphics/Rect"); 598 gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I"); 599 gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I"); 600 gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I"); 601 gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I"); 602 603 gRectF_class = make_globalref(env, "android/graphics/RectF"); 604 gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F"); 605 gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F"); 606 gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F"); 607 gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F"); 608 609 gPoint_class = make_globalref(env, "android/graphics/Point"); 610 gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I"); 611 gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I"); 612 613 gPointF_class = make_globalref(env, "android/graphics/PointF"); 614 gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F"); 615 gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F"); 616 617 gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); 618 gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I"); 619 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", 620 "(I[BZ[BI)V"); 621 gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder"); 622 gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V"); 623 624 gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config"); 625 gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class, 626 "nativeInt", "I"); 627 628 gCanvas_class = make_globalref(env, "android/graphics/Canvas"); 629 gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvas", "I"); 630 631 gPaint_class = make_globalref(env, "android/graphics/Paint"); 632 gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "I"); 633 634 gPicture_class = make_globalref(env, "android/graphics/Picture"); 635 gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "I"); 636 637 gRegion_class = make_globalref(env, "android/graphics/Region"); 638 gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "I"); 639 gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>", 640 "(II)V"); 641 642 return 0; 643} 644