1 #include "jni.h"
2 #include "GraphicsJNI.h"
3 #include "NIOBuffer.h"
4 #include "SkPicture.h"
5 #include "SkRegion.h"
6 #include <android_runtime/AndroidRuntime.h>
7
8 //#define REPORT_SIZE_TO_JVM
9 //#define TRACK_LOCK_COUNT
10
doThrow(JNIEnv * env,const char * exc,const char * msg)11 void doThrow(JNIEnv* env, const char* exc, const char* msg) {
12 // don't throw a new exception if we already have one pending
13 if (env->ExceptionCheck() == JNI_FALSE) {
14 jclass npeClazz;
15
16 npeClazz = env->FindClass(exc);
17 LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc);
18
19 env->ThrowNew(npeClazz, msg);
20 }
21 }
22
doThrowNPE(JNIEnv * env)23 void doThrowNPE(JNIEnv* env) {
24 doThrow(env, "java/lang/NullPointerException");
25 }
26
doThrowAIOOBE(JNIEnv * env)27 void doThrowAIOOBE(JNIEnv* env) {
28 doThrow(env, "java/lang/ArrayIndexOutOfBoundsException");
29 }
30
doThrowRE(JNIEnv * env,const char * msg)31 void doThrowRE(JNIEnv* env, const char* msg) {
32 doThrow(env, "java/lang/RuntimeException", msg);
33 }
34
doThrowIAE(JNIEnv * env,const char * msg)35 void doThrowIAE(JNIEnv* env, const char* msg) {
36 doThrow(env, "java/lang/IllegalArgumentException", msg);
37 }
38
doThrowISE(JNIEnv * env,const char * msg)39 void doThrowISE(JNIEnv* env, const char* msg) {
40 doThrow(env, "java/lang/IllegalStateException", msg);
41 }
42
doThrowOOME(JNIEnv * env,const char * msg)43 void doThrowOOME(JNIEnv* env, const char* msg) {
44 doThrow(env, "java/lang/OutOfMemoryError", msg);
45 }
46
hasException(JNIEnv * env)47 bool GraphicsJNI::hasException(JNIEnv *env) {
48 if (env->ExceptionCheck() != 0) {
49 LOGE("*** Uncaught exception returned from Java call!\n");
50 env->ExceptionDescribe();
51 return true;
52 }
53 return false;
54 }
55
56 ///////////////////////////////////////////////////////////////////////////////
57
AutoJavaFloatArray(JNIEnv * env,jfloatArray array,int minLength)58 AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
59 int minLength)
60 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
61 SkASSERT(env);
62 if (array) {
63 fLen = env->GetArrayLength(array);
64 if (fLen < minLength) {
65 sk_throw();
66 }
67 fPtr = env->GetFloatArrayElements(array, NULL);
68 }
69 }
70
~AutoJavaFloatArray()71 AutoJavaFloatArray::~AutoJavaFloatArray() {
72 if (fPtr) {
73 fEnv->ReleaseFloatArrayElements(fArray, fPtr, 0);
74 }
75 }
76
AutoJavaIntArray(JNIEnv * env,jintArray array,int minLength)77 AutoJavaIntArray::AutoJavaIntArray(JNIEnv* env, jintArray array,
78 int minLength)
79 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
80 SkASSERT(env);
81 if (array) {
82 fLen = env->GetArrayLength(array);
83 if (fLen < minLength) {
84 sk_throw();
85 }
86 fPtr = env->GetIntArrayElements(array, NULL);
87 }
88 }
89
~AutoJavaIntArray()90 AutoJavaIntArray::~AutoJavaIntArray() {
91 if (fPtr) {
92 fEnv->ReleaseIntArrayElements(fArray, fPtr, 0);
93 }
94 }
95
AutoJavaShortArray(JNIEnv * env,jshortArray array,int minLength)96 AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
97 int minLength)
98 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
99 SkASSERT(env);
100 if (array) {
101 fLen = env->GetArrayLength(array);
102 if (fLen < minLength) {
103 sk_throw();
104 }
105 fPtr = env->GetShortArrayElements(array, NULL);
106 }
107 }
108
~AutoJavaShortArray()109 AutoJavaShortArray::~AutoJavaShortArray() {
110 if (fPtr) {
111 fEnv->ReleaseShortArrayElements(fArray, fPtr, 0);
112 }
113 }
114
AutoJavaByteArray(JNIEnv * env,jbyteArray array,int minLength)115 AutoJavaByteArray::AutoJavaByteArray(JNIEnv* env, jbyteArray array,
116 int minLength)
117 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
118 SkASSERT(env);
119 if (array) {
120 fLen = env->GetArrayLength(array);
121 if (fLen < minLength) {
122 sk_throw();
123 }
124 fPtr = env->GetByteArrayElements(array, NULL);
125 }
126 }
127
~AutoJavaByteArray()128 AutoJavaByteArray::~AutoJavaByteArray() {
129 if (fPtr) {
130 fEnv->ReleaseByteArrayElements(fArray, fPtr, 0);
131 }
132 }
133
134 ///////////////////////////////////////////////////////////////////////////////
135
136 static jclass gRect_class;
137 static jfieldID gRect_leftFieldID;
138 static jfieldID gRect_topFieldID;
139 static jfieldID gRect_rightFieldID;
140 static jfieldID gRect_bottomFieldID;
141
142 static jclass gRectF_class;
143 static jfieldID gRectF_leftFieldID;
144 static jfieldID gRectF_topFieldID;
145 static jfieldID gRectF_rightFieldID;
146 static jfieldID gRectF_bottomFieldID;
147
148 static jclass gPoint_class;
149 static jfieldID gPoint_xFieldID;
150 static jfieldID gPoint_yFieldID;
151
152 static jclass gPointF_class;
153 static jfieldID gPointF_xFieldID;
154 static jfieldID gPointF_yFieldID;
155
156 static jclass gBitmap_class;
157 static jfieldID gBitmap_nativeInstanceID;
158 static jmethodID gBitmap_constructorMethodID;
159 static jmethodID gBitmap_allocBufferMethodID;
160
161 static jclass gBitmapConfig_class;
162 static jfieldID gBitmapConfig_nativeInstanceID;
163
164 static jclass gCanvas_class;
165 static jfieldID gCanvas_nativeInstanceID;
166
167 static jclass gPaint_class;
168 static jfieldID gPaint_nativeInstanceID;
169
170 static jclass gPicture_class;
171 static jfieldID gPicture_nativeInstanceID;
172
173 static jclass gRegion_class;
174 static jfieldID gRegion_nativeInstanceID;
175 static jmethodID gRegion_constructorMethodID;
176
177 static jobject gVMRuntime_singleton;
178 static jmethodID gVMRuntime_trackExternalAllocationMethodID;
179 static jmethodID gVMRuntime_trackExternalFreeMethodID;
180
181 ///////////////////////////////////////////////////////////////////////////////
182
get_jrect(JNIEnv * env,jobject obj,int * L,int * T,int * R,int * B)183 void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B)
184 {
185 SkASSERT(env->IsInstanceOf(obj, gRect_class));
186
187 *L = env->GetIntField(obj, gRect_leftFieldID);
188 *T = env->GetIntField(obj, gRect_topFieldID);
189 *R = env->GetIntField(obj, gRect_rightFieldID);
190 *B = env->GetIntField(obj, gRect_bottomFieldID);
191 }
192
set_jrect(JNIEnv * env,jobject obj,int L,int T,int R,int B)193 void GraphicsJNI::set_jrect(JNIEnv* env, jobject obj, int L, int T, int R, int B)
194 {
195 SkASSERT(env->IsInstanceOf(obj, gRect_class));
196
197 env->SetIntField(obj, gRect_leftFieldID, L);
198 env->SetIntField(obj, gRect_topFieldID, T);
199 env->SetIntField(obj, gRect_rightFieldID, R);
200 env->SetIntField(obj, gRect_bottomFieldID, B);
201 }
202
jrect_to_irect(JNIEnv * env,jobject obj,SkIRect * ir)203 SkIRect* GraphicsJNI::jrect_to_irect(JNIEnv* env, jobject obj, SkIRect* ir)
204 {
205 SkASSERT(env->IsInstanceOf(obj, gRect_class));
206
207 ir->set(env->GetIntField(obj, gRect_leftFieldID),
208 env->GetIntField(obj, gRect_topFieldID),
209 env->GetIntField(obj, gRect_rightFieldID),
210 env->GetIntField(obj, gRect_bottomFieldID));
211 return ir;
212 }
213
irect_to_jrect(const SkIRect & ir,JNIEnv * env,jobject obj)214 void GraphicsJNI::irect_to_jrect(const SkIRect& ir, JNIEnv* env, jobject obj)
215 {
216 SkASSERT(env->IsInstanceOf(obj, gRect_class));
217
218 env->SetIntField(obj, gRect_leftFieldID, ir.fLeft);
219 env->SetIntField(obj, gRect_topFieldID, ir.fTop);
220 env->SetIntField(obj, gRect_rightFieldID, ir.fRight);
221 env->SetIntField(obj, gRect_bottomFieldID, ir.fBottom);
222 }
223
jrectf_to_rect(JNIEnv * env,jobject obj,SkRect * r)224 SkRect* GraphicsJNI::jrectf_to_rect(JNIEnv* env, jobject obj, SkRect* r)
225 {
226 SkASSERT(env->IsInstanceOf(obj, gRectF_class));
227
228 r->set(SkFloatToScalar(env->GetFloatField(obj, gRectF_leftFieldID)),
229 SkFloatToScalar(env->GetFloatField(obj, gRectF_topFieldID)),
230 SkFloatToScalar(env->GetFloatField(obj, gRectF_rightFieldID)),
231 SkFloatToScalar(env->GetFloatField(obj, gRectF_bottomFieldID)));
232 return r;
233 }
234
jrect_to_rect(JNIEnv * env,jobject obj,SkRect * r)235 SkRect* GraphicsJNI::jrect_to_rect(JNIEnv* env, jobject obj, SkRect* r)
236 {
237 SkASSERT(env->IsInstanceOf(obj, gRect_class));
238
239 r->set(SkIntToScalar(env->GetIntField(obj, gRect_leftFieldID)),
240 SkIntToScalar(env->GetIntField(obj, gRect_topFieldID)),
241 SkIntToScalar(env->GetIntField(obj, gRect_rightFieldID)),
242 SkIntToScalar(env->GetIntField(obj, gRect_bottomFieldID)));
243 return r;
244 }
245
rect_to_jrectf(const SkRect & r,JNIEnv * env,jobject obj)246 void GraphicsJNI::rect_to_jrectf(const SkRect& r, JNIEnv* env, jobject obj)
247 {
248 SkASSERT(env->IsInstanceOf(obj, gRectF_class));
249
250 env->SetFloatField(obj, gRectF_leftFieldID, SkScalarToFloat(r.fLeft));
251 env->SetFloatField(obj, gRectF_topFieldID, SkScalarToFloat(r.fTop));
252 env->SetFloatField(obj, gRectF_rightFieldID, SkScalarToFloat(r.fRight));
253 env->SetFloatField(obj, gRectF_bottomFieldID, SkScalarToFloat(r.fBottom));
254 }
255
jpoint_to_ipoint(JNIEnv * env,jobject obj,SkIPoint * point)256 SkIPoint* GraphicsJNI::jpoint_to_ipoint(JNIEnv* env, jobject obj, SkIPoint* point)
257 {
258 SkASSERT(env->IsInstanceOf(obj, gPoint_class));
259
260 point->set(env->GetIntField(obj, gPoint_xFieldID),
261 env->GetIntField(obj, gPoint_yFieldID));
262 return point;
263 }
264
ipoint_to_jpoint(const SkIPoint & ir,JNIEnv * env,jobject obj)265 void GraphicsJNI::ipoint_to_jpoint(const SkIPoint& ir, JNIEnv* env, jobject obj)
266 {
267 SkASSERT(env->IsInstanceOf(obj, gPoint_class));
268
269 env->SetIntField(obj, gPoint_xFieldID, ir.fX);
270 env->SetIntField(obj, gPoint_yFieldID, ir.fY);
271 }
272
jpointf_to_point(JNIEnv * env,jobject obj,SkPoint * point)273 SkPoint* GraphicsJNI::jpointf_to_point(JNIEnv* env, jobject obj, SkPoint* point)
274 {
275 SkASSERT(env->IsInstanceOf(obj, gPointF_class));
276
277 point->set(SkFloatToScalar(env->GetIntField(obj, gPointF_xFieldID)),
278 SkFloatToScalar(env->GetIntField(obj, gPointF_yFieldID)));
279 return point;
280 }
281
point_to_jpointf(const SkPoint & r,JNIEnv * env,jobject obj)282 void GraphicsJNI::point_to_jpointf(const SkPoint& r, JNIEnv* env, jobject obj)
283 {
284 SkASSERT(env->IsInstanceOf(obj, gPointF_class));
285
286 env->SetFloatField(obj, gPointF_xFieldID, SkScalarToFloat(r.fX));
287 env->SetFloatField(obj, gPointF_yFieldID, SkScalarToFloat(r.fY));
288 }
289
getNativeBitmap(JNIEnv * env,jobject bitmap)290 SkBitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
291 SkASSERT(env);
292 SkASSERT(bitmap);
293 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
294 SkBitmap* b = (SkBitmap*)env->GetIntField(bitmap, gBitmap_nativeInstanceID);
295 SkASSERT(b);
296 return b;
297 }
298
getNativeBitmapConfig(JNIEnv * env,jobject jconfig)299 SkBitmap::Config GraphicsJNI::getNativeBitmapConfig(JNIEnv* env,
300 jobject jconfig) {
301 SkASSERT(env);
302 if (NULL == jconfig) {
303 return SkBitmap::kNo_Config;
304 }
305 SkASSERT(env->IsInstanceOf(jconfig, gBitmapConfig_class));
306 int c = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID);
307 if (c < 0 || c >= SkBitmap::kConfigCount) {
308 c = SkBitmap::kNo_Config;
309 }
310 return static_cast<SkBitmap::Config>(c);
311 }
312
getNativeCanvas(JNIEnv * env,jobject canvas)313 SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) {
314 SkASSERT(env);
315 SkASSERT(canvas);
316 SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
317 SkCanvas* c = (SkCanvas*)env->GetIntField(canvas, gCanvas_nativeInstanceID);
318 SkASSERT(c);
319 return c;
320 }
321
getNativePaint(JNIEnv * env,jobject paint)322 SkPaint* GraphicsJNI::getNativePaint(JNIEnv* env, jobject paint) {
323 SkASSERT(env);
324 SkASSERT(paint);
325 SkASSERT(env->IsInstanceOf(paint, gPaint_class));
326 SkPaint* p = (SkPaint*)env->GetIntField(paint, gPaint_nativeInstanceID);
327 SkASSERT(p);
328 return p;
329 }
330
getNativePicture(JNIEnv * env,jobject picture)331 SkPicture* GraphicsJNI::getNativePicture(JNIEnv* env, jobject picture)
332 {
333 SkASSERT(env);
334 SkASSERT(picture);
335 SkASSERT(env->IsInstanceOf(picture, gPicture_class));
336 SkPicture* p = (SkPicture*)env->GetIntField(picture, gPicture_nativeInstanceID);
337 SkASSERT(p);
338 return p;
339 }
340
getNativeRegion(JNIEnv * env,jobject region)341 SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
342 {
343 SkASSERT(env);
344 SkASSERT(region);
345 SkASSERT(env->IsInstanceOf(region, gRegion_class));
346 SkRegion* r = (SkRegion*)env->GetIntField(region, gRegion_nativeInstanceID);
347 SkASSERT(r);
348 return r;
349 }
350
351 ///////////////////////////////////////////////////////////////////////////////////////////
352
createBitmap(JNIEnv * env,SkBitmap * bitmap,bool isMutable,jbyteArray ninepatch,int density)353 jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
354 jbyteArray ninepatch, int density)
355 {
356 SkASSERT(bitmap != NULL);
357 SkASSERT(NULL != bitmap->pixelRef());
358
359 jobject obj = env->AllocObject(gBitmap_class);
360 if (obj) {
361 env->CallVoidMethod(obj, gBitmap_constructorMethodID,
362 (jint)bitmap, isMutable, ninepatch, density);
363 if (hasException(env)) {
364 obj = NULL;
365 }
366 }
367 return obj;
368 }
369
createRegion(JNIEnv * env,SkRegion * region)370 jobject GraphicsJNI::createRegion(JNIEnv* env, SkRegion* region)
371 {
372 SkASSERT(region != NULL);
373 jobject obj = env->AllocObject(gRegion_class);
374 if (obj) {
375 env->CallVoidMethod(obj, gRegion_constructorMethodID, (jint)region, 0);
376 if (hasException(env)) {
377 obj = NULL;
378 }
379 }
380 return obj;
381 }
382
383 #include "SkPixelRef.h"
384
vm2env(JavaVM * vm)385 static JNIEnv* vm2env(JavaVM* vm)
386 {
387 JNIEnv* env = NULL;
388 if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK || NULL == env)
389 {
390 SkDebugf("------- [%p] vm->GetEnv() failed\n", vm);
391 sk_throw();
392 }
393 return env;
394 }
395
396 #ifdef TRACK_LOCK_COUNT
397 static int gLockCount;
398 #endif
399
400 ///////////////////////////////////////////////////////////////////////////////
401
402 #include "SkMallocPixelRef.h"
403
404 /* Extend SkMallocPixelRef to inform the VM when we free up the storage
405 */
406 class AndroidPixelRef : public SkMallocPixelRef {
407 public:
408 /** Allocate the specified buffer for pixels. The memory is freed when the
409 last owner of this pixelref is gone. Our caller has already informed
410 the VM of our allocation.
411 */
AndroidPixelRef(JNIEnv * env,void * storage,size_t size,SkColorTable * ctable)412 AndroidPixelRef(JNIEnv* env, void* storage, size_t size,
413 SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable) {
414 SkASSERT(storage);
415 SkASSERT(env);
416
417 if (env->GetJavaVM(&fVM) != JNI_OK) {
418 SkDebugf("------ [%p] env->GetJavaVM failed\n", env);
419 sk_throw();
420 }
421 }
422
~AndroidPixelRef()423 virtual ~AndroidPixelRef() {
424 JNIEnv* env = vm2env(fVM);
425 // SkDebugf("-------------- inform VM we're releasing %d bytes\n", this->getSize());
426 jlong jsize = this->getSize(); // the VM wants longs for the size
427 env->CallVoidMethod(gVMRuntime_singleton,
428 gVMRuntime_trackExternalFreeMethodID,
429 jsize);
430 if (GraphicsJNI::hasException(env)) {
431 env->ExceptionClear();
432 }
433 }
434
435 private:
436 JavaVM* fVM;
437 };
438
setJavaPixelRef(JNIEnv * env,SkBitmap * bitmap,SkColorTable * ctable,bool reportSizeToVM)439 bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
440 SkColorTable* ctable, bool reportSizeToVM) {
441 Sk64 size64 = bitmap->getSize64();
442 if (size64.isNeg() || !size64.is32()) {
443 doThrow(env, "java/lang/IllegalArgumentException",
444 "bitmap size exceeds 32bits");
445 return false;
446 }
447
448 size_t size = size64.get32();
449 jlong jsize = size; // the VM wants longs for the size
450 if (reportSizeToVM) {
451 // SkDebugf("-------------- inform VM we've allocated %d bytes\n", size);
452 bool r = env->CallBooleanMethod(gVMRuntime_singleton,
453 gVMRuntime_trackExternalAllocationMethodID,
454 jsize);
455 if (GraphicsJNI::hasException(env)) {
456 return false;
457 }
458 if (!r) {
459 LOGE("VM won't let us allocate %zd bytes\n", size);
460 doThrowOOME(env, "bitmap size exceeds VM budget");
461 return false;
462 }
463 }
464 // call the version of malloc that returns null on failure
465 void* addr = sk_malloc_flags(size, 0);
466 if (NULL == addr) {
467 if (reportSizeToVM) {
468 // SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size);
469 // we didn't actually allocate it, so inform the VM
470 env->CallVoidMethod(gVMRuntime_singleton,
471 gVMRuntime_trackExternalFreeMethodID,
472 jsize);
473 if (!GraphicsJNI::hasException(env)) {
474 doThrowOOME(env, "bitmap size too large for malloc");
475 }
476 }
477 return false;
478 }
479
480 SkPixelRef* pr = reportSizeToVM ?
481 new AndroidPixelRef(env, addr, size, ctable) :
482 new SkMallocPixelRef(addr, size, ctable);
483 bitmap->setPixelRef(pr)->unref();
484 // since we're already allocated, we lockPixels right away
485 // HeapAllocator behaves this way too
486 bitmap->lockPixels();
487 return true;
488 }
489
490 ///////////////////////////////////////////////////////////////////////////////
491
JavaPixelAllocator(JNIEnv * env,bool reportSizeToVM)492 JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM)
493 : fEnv(env), fReportSizeToVM(reportSizeToVM) {}
494
allocPixelRef(SkBitmap * bitmap,SkColorTable * ctable)495 bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
496 return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable, fReportSizeToVM);
497 }
498
499 ////////////////////////////////////////////////////////////////////////////////
500
make_globalref(JNIEnv * env,const char classname[])501 static jclass make_globalref(JNIEnv* env, const char classname[])
502 {
503 jclass c = env->FindClass(classname);
504 SkASSERT(c);
505 return (jclass)env->NewGlobalRef(c);
506 }
507
getFieldIDCheck(JNIEnv * env,jclass clazz,const char fieldname[],const char type[])508 static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
509 const char fieldname[], const char type[])
510 {
511 jfieldID id = env->GetFieldID(clazz, fieldname, type);
512 SkASSERT(id);
513 return id;
514 }
515
register_android_graphics_Graphics(JNIEnv * env)516 int register_android_graphics_Graphics(JNIEnv* env)
517 {
518 jmethodID m;
519 jclass c;
520
521 gRect_class = make_globalref(env, "android/graphics/Rect");
522 gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I");
523 gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I");
524 gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I");
525 gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I");
526
527 gRectF_class = make_globalref(env, "android/graphics/RectF");
528 gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F");
529 gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F");
530 gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F");
531 gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F");
532
533 gPoint_class = make_globalref(env, "android/graphics/Point");
534 gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I");
535 gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I");
536
537 gPointF_class = make_globalref(env, "android/graphics/PointF");
538 gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F");
539 gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F");
540
541 gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
542 gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
543 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
544 "(IZ[BI)V");
545
546 gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config");
547 gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class,
548 "nativeInt", "I");
549
550 gCanvas_class = make_globalref(env, "android/graphics/Canvas");
551 gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvas", "I");
552
553 gPaint_class = make_globalref(env, "android/graphics/Paint");
554 gPaint_nativeInstanceID = getFieldIDCheck(env, gPaint_class, "mNativePaint", "I");
555
556 gPicture_class = make_globalref(env, "android/graphics/Picture");
557 gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "I");
558
559 gRegion_class = make_globalref(env, "android/graphics/Region");
560 gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "I");
561 gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>",
562 "(II)V");
563
564 // Get the VMRuntime class.
565 c = env->FindClass("dalvik/system/VMRuntime");
566 SkASSERT(c);
567 // Look up VMRuntime.getRuntime().
568 m = env->GetStaticMethodID(c, "getRuntime", "()Ldalvik/system/VMRuntime;");
569 SkASSERT(m);
570 // Call VMRuntime.getRuntime() and hold onto its result.
571 gVMRuntime_singleton = env->CallStaticObjectMethod(c, m);
572 SkASSERT(gVMRuntime_singleton);
573 gVMRuntime_singleton = (jobject)env->NewGlobalRef(gVMRuntime_singleton);
574 // Look up the VMRuntime methods we'll be using.
575 gVMRuntime_trackExternalAllocationMethodID =
576 env->GetMethodID(c, "trackExternalAllocation", "(J)Z");
577 gVMRuntime_trackExternalFreeMethodID =
578 env->GetMethodID(c, "trackExternalFree", "(J)V");
579
580 NIOBuffer::RegisterJNI(env);
581
582 return 0;
583 }
584
585