1 #include "SkBitmap.h"
\r
2 #include "SkPixelRef.h"
\r
3 #include "SkImageEncoder.h"
\r
4 #include "SkColorPriv.h"
\r
5 #include "GraphicsJNI.h"
\r
6 #include "SkDither.h"
\r
7 #include "SkUnPreMultiply.h"
\r
9 #include <binder/Parcel.h>
\r
10 #include "android_os_Parcel.h"
\r
11 #include "android_util_Binder.h"
\r
12 #include "android_nio_utils.h"
\r
13 #include "CreateJavaOutputStreamAdaptor.h"
\r
20 #define TRACE_BITMAP(code) code
\r
22 #define TRACE_BITMAP(code)
\r
25 ///////////////////////////////////////////////////////////////////////////////
\r
26 // Conversions to/from SkColor, for get/setPixels, and the create method, which
\r
27 // is basically like setPixels
\r
29 typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
\r
32 static void FromColor_D32(void* dst, const SkColor src[], int width,
\r
34 SkPMColor* d = (SkPMColor*)dst;
\r
36 for (int i = 0; i < width; i++) {
\r
37 *d++ = SkPreMultiplyColor(*src++);
\r
41 static void FromColor_D565(void* dst, const SkColor src[], int width,
\r
43 uint16_t* d = (uint16_t*)dst;
\r
46 for (int stop = x + width; x < stop; x++) {
\r
48 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
\r
53 static void FromColor_D4444(void* dst, const SkColor src[], int width,
\r
55 SkPMColor16* d = (SkPMColor16*)dst;
\r
57 DITHER_4444_SCAN(y);
\r
58 for (int stop = x + width; x < stop; x++) {
\r
59 SkPMColor c = SkPreMultiplyColor(*src++);
\r
60 *d++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
\r
61 // *d++ = SkPixel32ToPixel4444(c);
\r
66 static FromColorProc ChooseFromColorProc(SkBitmap::Config config) {
\r
68 case SkBitmap::kARGB_8888_Config:
\r
69 return FromColor_D32;
\r
70 case SkBitmap::kARGB_4444_Config:
\r
71 return FromColor_D4444;
\r
72 case SkBitmap::kRGB_565_Config:
\r
73 return FromColor_D565;
\r
80 bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
\r
81 int srcOffset, int srcStride,
\r
82 int x, int y, int width, int height,
\r
83 const SkBitmap& dstBitmap) {
\r
84 SkAutoLockPixels alp(dstBitmap);
\r
85 void* dst = dstBitmap.getPixels();
\r
86 FromColorProc proc = ChooseFromColorProc(dstBitmap.config());
\r
88 if (NULL == dst || NULL == proc) {
\r
92 const jint* array = env->GetIntArrayElements(srcColors, NULL);
\r
93 const SkColor* src = (const SkColor*)array + srcOffset;
\r
95 // reset to to actual choice from caller
\r
96 dst = dstBitmap.getAddr(x, y);
\r
97 // now copy/convert each scanline
\r
98 for (int y = 0; y < height; y++) {
\r
99 proc(dst, src, width, x, y);
\r
101 dst = (char*)dst + dstBitmap.rowBytes();
\r
104 dstBitmap.notifyPixelsChanged();
\r
106 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
\r
111 //////////////////// ToColor procs
\r
113 typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
\r
116 static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
\r
118 SkASSERT(width > 0);
\r
119 const SkPMColor* s = (const SkPMColor*)src;
\r
121 *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
\r
122 } while (--width != 0);
\r
125 static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
\r
127 SkASSERT(width > 0);
\r
128 const SkPMColor* s = (const SkPMColor*)src;
\r
130 SkPMColor c = *s++;
\r
131 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
\r
132 SkGetPackedB32(c));
\r
133 } while (--width != 0);
\r
136 static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
\r
138 SkASSERT(width > 0);
\r
139 const SkPMColor16* s = (const SkPMColor16*)src;
\r
141 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
\r
142 } while (--width != 0);
\r
145 static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
\r
147 SkASSERT(width > 0);
\r
148 const SkPMColor16* s = (const SkPMColor16*)src;
\r
150 SkPMColor c = SkPixel4444ToPixel32(*s++);
\r
151 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
\r
152 SkGetPackedB32(c));
\r
153 } while (--width != 0);
\r
156 static void ToColor_S565(SkColor dst[], const void* src, int width,
\r
158 SkASSERT(width > 0);
\r
159 const uint16_t* s = (const uint16_t*)src;
\r
162 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
\r
163 SkPacked16ToB32(c));
\r
164 } while (--width != 0);
\r
167 static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
\r
168 SkColorTable* ctable) {
\r
169 SkASSERT(width > 0);
\r
170 const uint8_t* s = (const uint8_t*)src;
\r
171 const SkPMColor* colors = ctable->lockColors();
\r
173 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
\r
174 } while (--width != 0);
\r
175 ctable->unlockColors(false);
\r
178 static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
\r
179 SkColorTable* ctable) {
\r
180 SkASSERT(width > 0);
\r
181 const uint8_t* s = (const uint8_t*)src;
\r
182 const SkPMColor* colors = ctable->lockColors();
\r
184 SkPMColor c = colors[*s++];
\r
185 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
\r
186 SkGetPackedB32(c));
\r
187 } while (--width != 0);
\r
188 ctable->unlockColors(false);
\r
192 static ToColorProc ChooseToColorProc(const SkBitmap& src) {
\r
193 switch (src.config()) {
\r
194 case SkBitmap::kARGB_8888_Config:
\r
195 return src.isOpaque() ? ToColor_S32_Opaque : ToColor_S32_Alpha;
\r
196 case SkBitmap::kARGB_4444_Config:
\r
197 return src.isOpaque() ? ToColor_S4444_Opaque : ToColor_S4444_Alpha;
\r
198 case SkBitmap::kRGB_565_Config:
\r
199 return ToColor_S565;
\r
200 case SkBitmap::kIndex8_Config:
\r
201 if (src.getColorTable() == NULL) {
\r
204 return src.isOpaque() ? ToColor_SI8_Opaque : ToColor_SI8_Alpha;
\r
211 ///////////////////////////////////////////////////////////////////////////////
\r
212 ///////////////////////////////////////////////////////////////////////////////
\r
214 static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
\r
215 int offset, int stride, int width, int height,
\r
216 SkBitmap::Config config, jboolean isMutable) {
\r
217 if (NULL != jColors) {
\r
218 size_t n = env->GetArrayLength(jColors);
\r
219 if (n < SkAbs32(stride) * (size_t)height) {
\r
220 doThrowAIOOBE(env);
\r
227 bitmap.setConfig(config, width, height);
\r
229 jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
\r
230 if (NULL == buff) {
\r
234 if (jColors != NULL) {
\r
235 GraphicsJNI::SetPixels(env, jColors, offset, stride,
\r
236 0, 0, width, height, bitmap);
\r
239 return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);
\r
242 static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
\r
243 SkBitmap::Config dstConfig, jboolean isMutable) {
\r
245 JavaPixelAllocator allocator(env);
\r
247 if (!src->copyTo(&result, dstConfig, &allocator)) {
\r
251 return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL, NULL);
\r
254 static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
255 #ifdef USE_OPENGL_RENDERER
\r
256 if (GraphicsJNI::useOpenglRenderer() && android::uirenderer::Caches::hasInstance()) {
257 android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
\r
260 #endif // USE_OPENGL_RENDERER
\r
264 static jboolean Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
265 #ifdef USE_OPENGL_RENDERER
\r
266 if (GraphicsJNI::useOpenglRenderer() && android::uirenderer::Caches::hasInstance()) {
267 return android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
\r
269 #endif // USE_OPENGL_RENDERER
\r
270 bitmap->setPixels(NULL, NULL);
\r
274 // These must match the int values in Bitmap.java
\r
275 enum JavaEncodeFormat {
\r
276 kJPEG_JavaEncodeFormat = 0,
\r
277 kPNG_JavaEncodeFormat = 1,
\r
278 kWEBP_JavaEncodeFormat = 2
\r
281 static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap,
\r
282 int format, int quality,
\r
283 jobject jstream, jbyteArray jstorage) {
\r
284 SkImageEncoder::Type fm;
\r
287 case kJPEG_JavaEncodeFormat:
\r
288 fm = SkImageEncoder::kJPEG_Type;
\r
290 case kPNG_JavaEncodeFormat:
\r
291 fm = SkImageEncoder::kPNG_Type;
\r
293 case kWEBP_JavaEncodeFormat:
\r
294 fm = SkImageEncoder::kWEBP_Type;
\r
300 bool success = false;
\r
301 if (NULL != bitmap) {
\r
302 SkAutoLockPixels alp(*bitmap);
\r
304 if (NULL == bitmap->getPixels()) {
\r
308 SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
\r
309 if (NULL == strm) {
\r
313 SkImageEncoder* encoder = SkImageEncoder::Create(fm);
\r
314 if (NULL != encoder) {
\r
315 success = encoder->encodeStream(strm, *bitmap, quality);
\r
323 static void Bitmap_erase(JNIEnv* env, jobject, SkBitmap* bitmap, jint color) {
\r
324 bitmap->eraseColor(color);
\r
327 static int Bitmap_width(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
328 return bitmap->width();
\r
331 static int Bitmap_height(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
332 return bitmap->height();
\r
335 static int Bitmap_rowBytes(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
336 return bitmap->rowBytes();
\r
339 static int Bitmap_config(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
340 return bitmap->config();
\r
343 static int Bitmap_getGenerationId(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
344 return bitmap->getGenerationID();
\r
347 static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
348 return !bitmap->isOpaque();
\r
351 static void Bitmap_setHasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap,
\r
352 jboolean hasAlpha) {
\r
353 bitmap->setIsOpaque(!hasAlpha);
\r
356 static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
357 return bitmap->hasHardwareMipMap();
\r
360 static void Bitmap_setHasMipMap(JNIEnv* env, jobject, SkBitmap* bitmap,
\r
361 jboolean hasMipMap) {
\r
362 bitmap->setHasHardwareMipMap(hasMipMap);
\r
365 ///////////////////////////////////////////////////////////////////////////////
\r
367 static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
\r
368 if (parcel == NULL) {
\r
369 SkDebugf("-------- unparcel parcel is NULL\n");
\r
373 android::Parcel* p = android::parcelForJavaObject(env, parcel);
\r
375 const bool isMutable = p->readInt32() != 0;
\r
376 const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
\r
377 const int width = p->readInt32();
\r
378 const int height = p->readInt32();
\r
379 const int rowBytes = p->readInt32();
\r
380 const int density = p->readInt32();
\r
382 if (SkBitmap::kARGB_8888_Config != config &&
\r
383 SkBitmap::kRGB_565_Config != config &&
\r
384 SkBitmap::kARGB_4444_Config != config &&
\r
385 SkBitmap::kIndex8_Config != config &&
\r
386 SkBitmap::kA8_Config != config) {
\r
387 SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
\r
391 SkBitmap* bitmap = new SkBitmap;
\r
393 bitmap->setConfig(config, width, height, rowBytes);
\r
395 SkColorTable* ctable = NULL;
\r
396 if (config == SkBitmap::kIndex8_Config) {
\r
397 int count = p->readInt32();
\r
399 size_t size = count * sizeof(SkPMColor);
\r
400 const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
\r
401 ctable = new SkColorTable(src, count);
\r
405 jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
\r
406 if (NULL == buffer) {
\r
407 SkSafeUnref(ctable);
\r
412 SkSafeUnref(ctable);
\r
414 size_t size = bitmap->getSize();
\r
416 android::Parcel::ReadableBlob blob;
\r
417 android::status_t status = p->readBlob(size, &blob);
\r
419 doThrowRE(env, "Could not read bitmap from parcel blob.");
\r
424 bitmap->lockPixels();
\r
425 memcpy(bitmap->getPixels(), blob.data(), size);
\r
426 bitmap->unlockPixels();
\r
429 return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, NULL, density);
\r
432 static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
\r
433 const SkBitmap* bitmap,
\r
434 jboolean isMutable, jint density,
\r
436 if (parcel == NULL) {
\r
437 SkDebugf("------- writeToParcel null parcel\n");
\r
441 android::Parcel* p = android::parcelForJavaObject(env, parcel);
\r
443 p->writeInt32(isMutable);
\r
444 p->writeInt32(bitmap->config());
\r
445 p->writeInt32(bitmap->width());
\r
446 p->writeInt32(bitmap->height());
\r
447 p->writeInt32(bitmap->rowBytes());
\r
448 p->writeInt32(density);
\r
450 if (bitmap->getConfig() == SkBitmap::kIndex8_Config) {
\r
451 SkColorTable* ctable = bitmap->getColorTable();
\r
452 if (ctable != NULL) {
\r
453 int count = ctable->count();
\r
454 p->writeInt32(count);
\r
455 memcpy(p->writeInplace(count * sizeof(SkPMColor)),
\r
456 ctable->lockColors(), count * sizeof(SkPMColor));
\r
457 ctable->unlockColors(false);
\r
459 p->writeInt32(0); // indicate no ctable
\r
463 size_t size = bitmap->getSize();
\r
465 android::Parcel::WritableBlob blob;
\r
466 android::status_t status = p->writeBlob(size, &blob);
\r
468 doThrowRE(env, "Could not write bitmap to parcel blob.");
\r
472 bitmap->lockPixels();
\r
473 const void* pSrc = bitmap->getPixels();
\r
474 if (pSrc == NULL) {
\r
475 memset(blob.data(), 0, size);
\r
477 memcpy(blob.data(), pSrc, size);
\r
479 bitmap->unlockPixels();
\r
485 static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
\r
486 const SkBitmap* src, const SkPaint* paint,
\r
487 jintArray offsetXY) {
\r
489 SkBitmap* dst = new SkBitmap;
\r
490 JavaPixelAllocator allocator(env);
\r
492 src->extractAlpha(dst, paint, &allocator, &offset);
\r
493 // If Skia can't allocate pixels for destination bitmap, it resets
\r
494 // it, that is set its pixels buffer to NULL, and zero width and height.
\r
495 if (dst->getPixels() == NULL && src->getPixels() != NULL) {
\r
497 doThrowOOME(env, "failed to allocate pixels for alpha");
\r
500 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
\r
501 int* array = env->GetIntArrayElements(offsetXY, NULL);
\r
502 array[0] = offset.fX;
\r
503 array[1] = offset.fY;
\r
504 env->ReleaseIntArrayElements(offsetXY, array, 0);
\r
507 return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL, NULL);
\r
510 ///////////////////////////////////////////////////////////////////////////////
\r
512 static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
\r
514 SkAutoLockPixels alp(*bitmap);
\r
516 ToColorProc proc = ChooseToColorProc(*bitmap);
\r
517 if (NULL == proc) {
\r
520 const void* src = bitmap->getAddr(x, y);
\r
526 proc(dst, src, 1, bitmap->getColorTable());
\r
530 static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
\r
531 jintArray pixelArray, int offset, int stride,
\r
532 int x, int y, int width, int height) {
\r
533 SkAutoLockPixels alp(*bitmap);
\r
535 ToColorProc proc = ChooseToColorProc(*bitmap);
\r
536 if (NULL == proc) {
\r
539 const void* src = bitmap->getAddr(x, y);
\r
544 SkColorTable* ctable = bitmap->getColorTable();
\r
545 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
\r
546 SkColor* d = (SkColor*)dst + offset;
\r
547 while (--height >= 0) {
\r
548 proc(d, src, width, ctable);
\r
550 src = (void*)((const char*)src + bitmap->rowBytes());
\r
552 env->ReleaseIntArrayElements(pixelArray, dst, 0);
\r
555 ///////////////////////////////////////////////////////////////////////////////
\r
557 static void Bitmap_setPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
\r
558 int x, int y, SkColor color) {
\r
559 SkAutoLockPixels alp(*bitmap);
\r
560 if (NULL == bitmap->getPixels()) {
\r
564 FromColorProc proc = ChooseFromColorProc(bitmap->config());
\r
565 if (NULL == proc) {
\r
569 proc(bitmap->getAddr(x, y), &color, 1, x, y);
\r
570 bitmap->notifyPixelsChanged();
\r
573 static void Bitmap_setPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
\r
574 jintArray pixelArray, int offset, int stride,
\r
575 int x, int y, int width, int height) {
\r
576 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
\r
577 x, y, width, height, *bitmap);
\r
580 static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
\r
581 const SkBitmap* bitmap, jobject jbuffer) {
\r
582 SkAutoLockPixels alp(*bitmap);
\r
583 const void* src = bitmap->getPixels();
\r
586 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
\r
588 // the java side has already checked that buffer is large enough
\r
589 memcpy(abp.pointer(), src, bitmap->getSize());
\r
593 static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
\r
594 const SkBitmap* bitmap, jobject jbuffer) {
\r
595 SkAutoLockPixels alp(*bitmap);
\r
596 void* dst = bitmap->getPixels();
\r
599 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
\r
600 // the java side has already checked that buffer is large enough
\r
601 memcpy(dst, abp.pointer(), bitmap->getSize());
\r
602 bitmap->notifyPixelsChanged();
\r
606 static bool Bitmap_sameAs(JNIEnv* env, jobject, const SkBitmap* bm0,
\r
607 const SkBitmap* bm1) {
\r
608 if (bm0->width() != bm1->width() ||
\r
609 bm0->height() != bm1->height() ||
\r
610 bm0->config() != bm1->config()) {
\r
614 SkAutoLockPixels alp0(*bm0);
\r
615 SkAutoLockPixels alp1(*bm1);
\r
617 // if we can't load the pixels, return false
\r
618 if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {
\r
622 if (bm0->config() == SkBitmap::kIndex8_Config) {
\r
623 SkColorTable* ct0 = bm0->getColorTable();
\r
624 SkColorTable* ct1 = bm1->getColorTable();
\r
625 if (NULL == ct0 || NULL == ct1) {
\r
628 if (ct0->count() != ct1->count()) {
\r
632 SkAutoLockColors alc0(ct0);
\r
633 SkAutoLockColors alc1(ct1);
\r
634 const size_t size = ct0->count() * sizeof(SkPMColor);
\r
635 if (memcmp(alc0.colors(), alc1.colors(), size) != 0) {
\r
640 // now compare each scanline. We can't do the entire buffer at once,
\r
641 // since we don't care about the pixel values that might extend beyond
\r
642 // the width (since the scanline might be larger than the logical width)
\r
643 const int h = bm0->height();
\r
644 const size_t size = bm0->width() * bm0->bytesPerPixel();
\r
645 for (int y = 0; y < h; y++) {
\r
646 if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {
\r
653 static void Bitmap_prepareToDraw(JNIEnv* env, jobject, SkBitmap* bitmap) {
\r
654 bitmap->lockPixels();
\r
655 bitmap->unlockPixels();
\r
658 ///////////////////////////////////////////////////////////////////////////////
\r
660 #include <android_runtime/AndroidRuntime.h>
\r
662 static JNINativeMethod gBitmapMethods[] = {
\r
663 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
\r
664 (void*)Bitmap_creator },
\r
665 { "nativeCopy", "(IIZ)Landroid/graphics/Bitmap;",
\r
666 (void*)Bitmap_copy },
\r
667 { "nativeDestructor", "(I)V", (void*)Bitmap_destructor },
\r
668 { "nativeRecycle", "(I)Z", (void*)Bitmap_recycle },
\r
669 { "nativeCompress", "(IIILjava/io/OutputStream;[B)Z",
\r
670 (void*)Bitmap_compress },
\r
671 { "nativeErase", "(II)V", (void*)Bitmap_erase },
\r
672 { "nativeWidth", "(I)I", (void*)Bitmap_width },
\r
673 { "nativeHeight", "(I)I", (void*)Bitmap_height },
\r
674 { "nativeRowBytes", "(I)I", (void*)Bitmap_rowBytes },
\r
675 { "nativeConfig", "(I)I", (void*)Bitmap_config },
\r
676 { "nativeHasAlpha", "(I)Z", (void*)Bitmap_hasAlpha },
\r
677 { "nativeSetHasAlpha", "(IZ)V", (void*)Bitmap_setHasAlpha },
\r
678 { "nativeHasMipMap", "(I)Z", (void*)Bitmap_hasMipMap },
\r
679 { "nativeSetHasMipMap", "(IZ)V", (void*)Bitmap_setHasMipMap },
\r
680 { "nativeCreateFromParcel",
\r
681 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
\r
682 (void*)Bitmap_createFromParcel },
\r
683 { "nativeWriteToParcel", "(IZILandroid/os/Parcel;)Z",
\r
684 (void*)Bitmap_writeToParcel },
\r
685 { "nativeExtractAlpha", "(II[I)Landroid/graphics/Bitmap;",
\r
686 (void*)Bitmap_extractAlpha },
\r
687 { "nativeGenerationId", "(I)I", (void*)Bitmap_getGenerationId },
\r
688 { "nativeGetPixel", "(III)I", (void*)Bitmap_getPixel },
\r
689 { "nativeGetPixels", "(I[IIIIIII)V", (void*)Bitmap_getPixels },
\r
690 { "nativeSetPixel", "(IIII)V", (void*)Bitmap_setPixel },
\r
691 { "nativeSetPixels", "(I[IIIIIII)V", (void*)Bitmap_setPixels },
\r
692 { "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",
\r
693 (void*)Bitmap_copyPixelsToBuffer },
\r
694 { "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",
\r
695 (void*)Bitmap_copyPixelsFromBuffer },
\r
696 { "nativeSameAs", "(II)Z", (void*)Bitmap_sameAs },
\r
697 { "nativePrepareToDraw", "(I)V", (void*)Bitmap_prepareToDraw },
\r
700 #define kClassPathName "android/graphics/Bitmap"
\r
702 int register_android_graphics_Bitmap(JNIEnv* env)
\r
704 return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
\r
705 gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods));
\r