blob: 88bbafd772c95dc69d894459ce68dc853af84162 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001#include "SkBitmap.h"
2#include "SkImageEncoder.h"
3#include "SkColorPriv.h"
4#include "GraphicsJNI.h"
5#include "SkDither.h"
6#include "SkUnPreMultiply.h"
7
Mathias Agopian07952722009-05-19 19:08:10 -07008#include <binder/Parcel.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009#include "android_util_Binder.h"
10#include "android_nio_utils.h"
11#include "CreateJavaOutputStreamAdaptor.h"
12
13#include <jni.h>
14
15#if 0
16 #define TRACE_BITMAP(code) code
17#else
18 #define TRACE_BITMAP(code)
19#endif
20
21///////////////////////////////////////////////////////////////////////////////
22// Conversions to/from SkColor, for get/setPixels, and the create method, which
23// is basically like setPixels
24
25typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
26 int x, int y);
27
28static void FromColor_D32(void* dst, const SkColor src[], int width,
29 int, int) {
30 SkPMColor* d = (SkPMColor*)dst;
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +080031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032 for (int i = 0; i < width; i++) {
33 *d++ = SkPreMultiplyColor(*src++);
34 }
35}
36
37static void FromColor_D565(void* dst, const SkColor src[], int width,
38 int x, int y) {
39 uint16_t* d = (uint16_t*)dst;
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +080040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 DITHER_565_SCAN(y);
42 for (int stop = x + width; x < stop; x++) {
43 SkColor c = *src++;
44 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
45 DITHER_VALUE(x));
46 }
47}
48
49static void FromColor_D4444(void* dst, const SkColor src[], int width,
50 int x, int y) {
51 SkPMColor16* d = (SkPMColor16*)dst;
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +080052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053 DITHER_4444_SCAN(y);
54 for (int stop = x + width; x < stop; x++) {
55 SkPMColor c = SkPreMultiplyColor(*src++);
56 *d++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
57// *d++ = SkPixel32ToPixel4444(c);
58 }
59}
60
61// can return NULL
62static FromColorProc ChooseFromColorProc(SkBitmap::Config config) {
63 switch (config) {
64 case SkBitmap::kARGB_8888_Config:
65 return FromColor_D32;
66 case SkBitmap::kARGB_4444_Config:
67 return FromColor_D4444;
68 case SkBitmap::kRGB_565_Config:
69 return FromColor_D565;
70 default:
71 break;
72 }
73 return NULL;
74}
75
76bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors,
77 int srcOffset, int srcStride,
78 int x, int y, int width, int height,
79 const SkBitmap& dstBitmap) {
80 SkAutoLockPixels alp(dstBitmap);
81 void* dst = dstBitmap.getPixels();
82 FromColorProc proc = ChooseFromColorProc(dstBitmap.config());
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +080083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 if (NULL == dst || NULL == proc) {
85 return false;
86 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +080087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 const jint* array = env->GetIntArrayElements(srcColors, NULL);
89 const SkColor* src = (const SkColor*)array + srcOffset;
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +080090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 // reset to to actual choice from caller
92 dst = dstBitmap.getAddr(x, y);
93 // now copy/convert each scanline
94 for (int y = 0; y < height; y++) {
95 proc(dst, src, width, x, y);
96 src += srcStride;
97 dst = (char*)dst + dstBitmap.rowBytes();
98 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +080099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
101 JNI_ABORT);
102 return true;
103}
104
105//////////////////// ToColor procs
106
107typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
108 SkColorTable*);
109
110static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
111 SkColorTable*) {
112 SkASSERT(width > 0);
113 const SkPMColor* s = (const SkPMColor*)src;
114 do {
115 *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
116 } while (--width != 0);
117}
118
119static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
120 SkColorTable*) {
121 SkASSERT(width > 0);
122 const SkPMColor* s = (const SkPMColor*)src;
123 do {
124 SkPMColor c = *s++;
125 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
126 SkGetPackedB32(c));
127 } while (--width != 0);
128}
129
130static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
131 SkColorTable*) {
132 SkASSERT(width > 0);
133 const SkPMColor16* s = (const SkPMColor16*)src;
134 do {
135 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
136 } while (--width != 0);
137}
138
139static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
140 SkColorTable*) {
141 SkASSERT(width > 0);
142 const SkPMColor* s = (const SkPMColor*)src;
143 do {
144 SkPMColor c = SkPixel4444ToPixel32(*s++);
145 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
146 SkGetPackedB32(c));
147 } while (--width != 0);
148}
149
150static void ToColor_S565(SkColor dst[], const void* src, int width,
151 SkColorTable*) {
152 SkASSERT(width > 0);
153 const uint16_t* s = (const uint16_t*)src;
154 do {
155 uint16_t c = *s++;
156 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
157 SkPacked16ToB32(c));
158 } while (--width != 0);
159}
160
161static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
162 SkColorTable* ctable) {
163 SkASSERT(width > 0);
164 const uint8_t* s = (const uint8_t*)src;
165 const SkPMColor* colors = ctable->lockColors();
166 do {
167 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
168 } while (--width != 0);
169 ctable->unlockColors(false);
170}
171
172static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
173 SkColorTable* ctable) {
174 SkASSERT(width > 0);
175 const uint8_t* s = (const uint8_t*)src;
176 const SkPMColor* colors = ctable->lockColors();
177 do {
178 SkPMColor c = colors[*s++];
179 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
180 SkGetPackedB32(c));
181 } while (--width != 0);
182 ctable->unlockColors(false);
183}
184
185// can return NULL
186static ToColorProc ChooseToColorProc(const SkBitmap& src) {
187 switch (src.config()) {
188 case SkBitmap::kARGB_8888_Config:
189 return src.isOpaque() ? ToColor_S32_Opaque : ToColor_S32_Alpha;
190 case SkBitmap::kARGB_4444_Config:
191 return src.isOpaque() ? ToColor_S4444_Opaque : ToColor_S4444_Alpha;
192 case SkBitmap::kRGB_565_Config:
193 return ToColor_S565;
194 case SkBitmap::kIndex8_Config:
195 if (src.getColorTable() == NULL) {
196 return NULL;
197 }
198 return src.isOpaque() ? ToColor_SI8_Opaque : ToColor_SI8_Alpha;
199 default:
200 break;
201 }
202 return NULL;
203}
204
205///////////////////////////////////////////////////////////////////////////////
206///////////////////////////////////////////////////////////////////////////////
207
208static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
209 int offset, int stride, int width, int height,
210 SkBitmap::Config config, jboolean isMutable) {
211 if (width <= 0 || height <= 0) {
212 doThrowIAE(env, "width and height must be > 0");
213 return NULL;
214 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 if (NULL != jColors) {
217 size_t n = env->GetArrayLength(jColors);
218 if (n < SkAbs32(stride) * (size_t)height) {
219 doThrowAIOOBE(env);
220 return NULL;
221 }
222 }
223
224 SkBitmap bitmap;
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 bitmap.setConfig(config, width, height);
Mike Reed1b22b972009-07-17 11:21:47 -0400227 if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 return NULL;
229 }
230
231 if (jColors != NULL) {
232 GraphicsJNI::SetPixels(env, jColors, offset, stride,
233 0, 0, width, height, bitmap);
234 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), isMutable,
237 NULL);
238}
239
240static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
241 SkBitmap::Config dstConfig, jboolean isMutable) {
242 SkBitmap result;
Mike Reed1b22b972009-07-17 11:21:47 -0400243 JavaPixelAllocator allocator(env, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244
245 if (!src->copyTo(&result, dstConfig, &allocator)) {
246 return NULL;
247 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 return GraphicsJNI::createBitmap(env, new SkBitmap(result), isMutable,
250 NULL);
251}
252
253static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
254 delete bitmap;
255}
256
257static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
258 bitmap->setPixels(NULL, NULL);
259}
260
261// These must match the int values in Bitmap.java
262enum JavaEncodeFormat {
263 kJPEG_JavaEncodeFormat = 0,
264 kPNG_JavaEncodeFormat = 1
265};
266
267static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap,
268 int format, int quality,
269 jobject jstream, jbyteArray jstorage) {
270 SkImageEncoder::Type fm;
271
272 switch (format) {
273 case kJPEG_JavaEncodeFormat:
274 fm = SkImageEncoder::kJPEG_Type;
275 break;
276 case kPNG_JavaEncodeFormat:
277 fm = SkImageEncoder::kPNG_Type;
278 break;
279 default:
280 return false;
281 }
282
283 bool success = false;
284 SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
285 if (NULL != strm) {
286 SkImageEncoder* encoder = SkImageEncoder::Create(fm);
287 if (NULL != encoder) {
288 success = encoder->encodeStream(strm, *bitmap, quality);
289 delete encoder;
290 }
291 delete strm;
292 }
293 return success;
294}
295
296static void Bitmap_erase(JNIEnv* env, jobject, SkBitmap* bitmap, jint color) {
297 bitmap->eraseColor(color);
298}
299
300static int Bitmap_width(JNIEnv* env, jobject, SkBitmap* bitmap) {
301 return bitmap->width();
302}
303
304static int Bitmap_height(JNIEnv* env, jobject, SkBitmap* bitmap) {
305 return bitmap->height();
306}
307
308static int Bitmap_rowBytes(JNIEnv* env, jobject, SkBitmap* bitmap) {
309 return bitmap->rowBytes();
310}
311
312static int Bitmap_config(JNIEnv* env, jobject, SkBitmap* bitmap) {
313 return bitmap->config();
314}
315
316static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap) {
317 return !bitmap->isOpaque();
318}
319
Mike Reeda78b0a22009-10-07 11:38:05 -0700320static void Bitmap_setHasAlpha(JNIEnv* env, jobject, SkBitmap* bitmap,
321 jboolean hasAlpha) {
322 bitmap->setIsOpaque(!hasAlpha);
323}
324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325///////////////////////////////////////////////////////////////////////////////
326
327static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
328 if (parcel == NULL) {
329 SkDebugf("-------- unparcel parcel is NULL\n");
330 return NULL;
331 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 android::Parcel* p = android::parcelForJavaObject(env, parcel);
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 const bool isMutable = p->readInt32() != 0;
336 const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
337 const int width = p->readInt32();
338 const int height = p->readInt32();
339 const int rowBytes = p->readInt32();
Dianne Hackbornde0dfb72009-09-23 14:09:34 -0700340 const int density = p->readInt32();
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 if (SkBitmap::kARGB_8888_Config != config &&
343 SkBitmap::kRGB_565_Config != config &&
344 SkBitmap::kARGB_4444_Config != config &&
345 SkBitmap::kIndex8_Config != config &&
346 SkBitmap::kA8_Config != config) {
347 SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
348 return NULL;
349 }
350
351 SkBitmap* bitmap = new SkBitmap;
352
353 bitmap->setConfig(config, width, height, rowBytes);
354
355 SkColorTable* ctable = NULL;
356 if (config == SkBitmap::kIndex8_Config) {
357 int count = p->readInt32();
358 if (count > 0) {
359 size_t size = count * sizeof(SkPMColor);
360 const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
361 ctable = new SkColorTable(src, count);
362 }
363 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800364
Mike Reed1b22b972009-07-17 11:21:47 -0400365 if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 ctable->safeUnref();
367 delete bitmap;
368 return NULL;
369 }
370
371 ctable->safeUnref();
372
373 size_t size = bitmap->getSize();
374 bitmap->lockPixels();
375 memcpy(bitmap->getPixels(), p->readInplace(size), size);
376 bitmap->unlockPixels();
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800377
Dianne Hackbornde0dfb72009-09-23 14:09:34 -0700378 return GraphicsJNI::createBitmap(env, bitmap, isMutable, NULL, density);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379}
380
381static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
382 const SkBitmap* bitmap,
Dianne Hackbornde0dfb72009-09-23 14:09:34 -0700383 jboolean isMutable, jint density,
384 jobject parcel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 if (parcel == NULL) {
386 SkDebugf("------- writeToParcel null parcel\n");
387 return false;
388 }
389
390 android::Parcel* p = android::parcelForJavaObject(env, parcel);
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 p->writeInt32(isMutable);
393 p->writeInt32(bitmap->config());
394 p->writeInt32(bitmap->width());
395 p->writeInt32(bitmap->height());
396 p->writeInt32(bitmap->rowBytes());
Dianne Hackbornde0dfb72009-09-23 14:09:34 -0700397 p->writeInt32(density);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398
399 if (bitmap->getConfig() == SkBitmap::kIndex8_Config) {
400 SkColorTable* ctable = bitmap->getColorTable();
401 if (ctable != NULL) {
402 int count = ctable->count();
403 p->writeInt32(count);
404 memcpy(p->writeInplace(count * sizeof(SkPMColor)),
405 ctable->lockColors(), count * sizeof(SkPMColor));
406 ctable->unlockColors(false);
407 } else {
408 p->writeInt32(0); // indicate no ctable
409 }
410 }
411
412 size_t size = bitmap->getSize();
413 bitmap->lockPixels();
414 memcpy(p->writeInplace(size), bitmap->getPixels(), size);
415 bitmap->unlockPixels();
416 return true;
417}
418
419static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
420 const SkBitmap* src, const SkPaint* paint,
421 jintArray offsetXY) {
422 SkIPoint offset;
423 SkBitmap* dst = new SkBitmap;
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 src->extractAlpha(dst, paint, &offset);
426 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
427 int* array = env->GetIntArrayElements(offsetXY, NULL);
428 array[0] = offset.fX;
429 array[1] = offset.fY;
430 env->ReleaseIntArrayElements(offsetXY, array, 0);
431 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 return GraphicsJNI::createBitmap(env, dst, true, NULL);
434}
435
436///////////////////////////////////////////////////////////////////////////////
437
438static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
439 int x, int y) {
440 SkAutoLockPixels alp(*bitmap);
441
442 ToColorProc proc = ChooseToColorProc(*bitmap);
443 if (NULL == proc) {
444 return 0;
445 }
446 const void* src = bitmap->getAddr(x, y);
447 if (NULL == src) {
448 return 0;
449 }
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 SkColor dst[1];
452 proc(dst, src, 1, bitmap->getColorTable());
453 return dst[0];
454}
455
456static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
457 jintArray pixelArray, int offset, int stride,
458 int x, int y, int width, int height) {
459 SkAutoLockPixels alp(*bitmap);
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 ToColorProc proc = ChooseToColorProc(*bitmap);
462 if (NULL == proc) {
463 return;
464 }
465 const void* src = bitmap->getAddr(x, y);
466 if (NULL == src) {
467 return;
468 }
469
470 SkColorTable* ctable = bitmap->getColorTable();
471 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
472 SkColor* d = (SkColor*)dst + offset;
473 while (--height >= 0) {
474 proc(d, src, width, ctable);
475 d += stride;
476 src = (void*)((const char*)src + bitmap->rowBytes());
477 }
478 env->ReleaseIntArrayElements(pixelArray, dst, 0);
479}
480
481///////////////////////////////////////////////////////////////////////////////
482
483static void Bitmap_setPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
484 int x, int y, SkColor color) {
485 SkAutoLockPixels alp(*bitmap);
486 if (NULL == bitmap->getPixels()) {
487 return;
488 }
489
490 FromColorProc proc = ChooseFromColorProc(bitmap->config());
491 if (NULL == proc) {
492 return;
493 }
494
495 proc(bitmap->getAddr(x, y), &color, 1, x, y);
496}
497
498static void Bitmap_setPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
499 jintArray pixelArray, int offset, int stride,
500 int x, int y, int width, int height) {
501 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
502 x, y, width, height, *bitmap);
503}
504
505static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
506 const SkBitmap* bitmap, jobject jbuffer) {
507 SkAutoLockPixels alp(*bitmap);
508 const void* src = bitmap->getPixels();
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 if (NULL != src) {
511 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
512
513 // the java side has already checked that buffer is large enough
514 memcpy(abp.pointer(), src, bitmap->getSize());
515 }
516}
517
518static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
519 const SkBitmap* bitmap, jobject jbuffer) {
520 SkAutoLockPixels alp(*bitmap);
521 void* dst = bitmap->getPixels();
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 if (NULL != dst) {
524 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
525 // the java side has already checked that buffer is large enough
526 memcpy(dst, abp.pointer(), bitmap->getSize());
527 }
528}
529
Mike Reed76d1e012010-03-05 17:42:30 -0500530static bool Bitmap_sameAs(JNIEnv* env, jobject, const SkBitmap* bm0,
531 const SkBitmap* bm1) {
532 if (bm0->width() != bm1->width() ||
533 bm0->height() != bm1->height() ||
534 bm0->config() != bm1->config()) {
535 return false;
536 }
537
538 SkAutoLockPixels alp0(*bm0);
539 SkAutoLockPixels alp1(*bm1);
540
541 // if we can't load the pixels, return false
542 if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {
543 return false;
544 }
545
546 if (bm0->config() == SkBitmap::kIndex8_Config) {
547 SkColorTable* ct0 = bm0->getColorTable();
548 SkColorTable* ct1 = bm1->getColorTable();
549 if (NULL == ct0 || NULL == ct1) {
550 return false;
551 }
552 if (ct0->count() != ct1->count()) {
553 return false;
554 }
555
556 SkAutoLockColors alc0(ct0);
557 SkAutoLockColors alc1(ct1);
558 const size_t size = ct0->count() * sizeof(SkPMColor);
559 if (memcmp(alc0.colors(), alc1.colors(), size) != 0) {
560 return false;
561 }
562 }
563
564 // now compare each scanline. We can't do the entire buffer at once,
565 // since we don't care about the pixel values that might extend beyond
566 // the width (since the scanline might be larger than the logical width)
567 const int h = bm0->height();
568 const size_t size = bm0->width() * bm0->bytesPerPixel();
569 for (int y = 0; y < h; y++) {
570 if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {
571 return false;
572 }
573 }
574 return true;
575}
576
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800577static void Bitmap_prepareToDraw(JNIEnv* env, jobject, SkBitmap* bitmap) {
578 bitmap->lockPixels();
579 bitmap->unlockPixels();
580}
581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582///////////////////////////////////////////////////////////////////////////////
583
584#include <android_runtime/AndroidRuntime.h>
585
586static JNINativeMethod gBitmapMethods[] = {
587 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
588 (void*)Bitmap_creator },
589 { "nativeCopy", "(IIZ)Landroid/graphics/Bitmap;",
590 (void*)Bitmap_copy },
591 { "nativeDestructor", "(I)V", (void*)Bitmap_destructor },
592 { "nativeRecycle", "(I)V", (void*)Bitmap_recycle },
593 { "nativeCompress", "(IIILjava/io/OutputStream;[B)Z",
594 (void*)Bitmap_compress },
595 { "nativeErase", "(II)V", (void*)Bitmap_erase },
596 { "nativeWidth", "(I)I", (void*)Bitmap_width },
597 { "nativeHeight", "(I)I", (void*)Bitmap_height },
598 { "nativeRowBytes", "(I)I", (void*)Bitmap_rowBytes },
599 { "nativeConfig", "(I)I", (void*)Bitmap_config },
600 { "nativeHasAlpha", "(I)Z", (void*)Bitmap_hasAlpha },
Mike Reeda78b0a22009-10-07 11:38:05 -0700601 { "nativeSetHasAlpha", "(IZ)V", (void*)Bitmap_setHasAlpha },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 { "nativeCreateFromParcel",
603 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
604 (void*)Bitmap_createFromParcel },
Dianne Hackbornde0dfb72009-09-23 14:09:34 -0700605 { "nativeWriteToParcel", "(IZILandroid/os/Parcel;)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 (void*)Bitmap_writeToParcel },
607 { "nativeExtractAlpha", "(II[I)Landroid/graphics/Bitmap;",
608 (void*)Bitmap_extractAlpha },
609 { "nativeGetPixel", "(III)I", (void*)Bitmap_getPixel },
610 { "nativeGetPixels", "(I[IIIIIII)V", (void*)Bitmap_getPixels },
611 { "nativeSetPixel", "(IIII)V", (void*)Bitmap_setPixel },
612 { "nativeSetPixels", "(I[IIIIIII)V", (void*)Bitmap_setPixels },
613 { "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",
614 (void*)Bitmap_copyPixelsToBuffer },
615 { "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",
Wei-Ta Chen8cdcb122009-06-18 19:14:38 +0800616 (void*)Bitmap_copyPixelsFromBuffer },
Mike Reed76d1e012010-03-05 17:42:30 -0500617 { "nativeSameAs", "(II)Z", (void*)Bitmap_sameAs },
618 { "nativePrepareToDraw", "(I)V", (void*)Bitmap_prepareToDraw },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619};
620
621#define kClassPathName "android/graphics/Bitmap"
622
623int register_android_graphics_Bitmap(JNIEnv* env);
624int register_android_graphics_Bitmap(JNIEnv* env)
625{
626 return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
627 gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods));
628}
629