blob: 178e073425551d0e8d79c165109116d1a27fdd16 [file] [log] [blame]
John Reckf29ed282015-04-07 07:32:03 -07001#define LOG_TAG "Bitmap"
John Reckf29ed282015-04-07 07:32:03 -07002#include "Bitmap.h"
3
Chris Craik32054b02014-05-09 13:58:56 -07004#include "SkBitmap.h"
5#include "SkPixelRef.h"
6#include "SkImageEncoder.h"
Leon Scroggins III57ee6202014-06-04 18:51:07 -04007#include "SkImageInfo.h"
Chris Craik32054b02014-05-09 13:58:56 -07008#include "SkColorPriv.h"
9#include "GraphicsJNI.h"
10#include "SkDither.h"
11#include "SkUnPreMultiply.h"
12#include "SkStream.h"
13
14#include <binder/Parcel.h>
15#include "android_os_Parcel.h"
16#include "android_util_Binder.h"
17#include "android_nio_utils.h"
18#include "CreateJavaOutputStreamAdaptor.h"
sergeyvdccca442016-03-21 15:38:21 -070019#include <hwui/Paint.h>
sergeyvc1c54062016-10-19 18:47:26 -070020#include <hwui/Bitmap.h>
John Reck43871902016-08-01 14:39:24 -070021#include <renderthread/RenderProxy.h>
Chris Craik32054b02014-05-09 13:58:56 -070022
Andreas Gampeed6b9df2014-11-20 22:02:20 -080023#include "core_jni_helpers.h"
24
Chris Craik32054b02014-05-09 13:58:56 -070025#include <jni.h>
Riley Andrews39d7f302014-11-13 17:43:25 -080026#include <memory>
27#include <string>
Chris Craik32054b02014-05-09 13:58:56 -070028
Jeff Browna316c5d2015-06-05 15:14:06 -070029#define DEBUG_PARCEL 0
Riley Andrews8cee7c12015-11-01 23:36:04 -080030#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
Jeff Browna316c5d2015-06-05 15:14:06 -070031
sergeyvc69853c2016-10-07 14:14:09 -070032static jclass gBitmap_class;
33static jfieldID gBitmap_nativePtr;
34static jmethodID gBitmap_constructorMethodID;
35static jmethodID gBitmap_reinitMethodID;
36static jmethodID gBitmap_getAllocationByteCountMethodID;
37
John Reckf29ed282015-04-07 07:32:03 -070038namespace android {
39
sergeyvc1c54062016-10-19 18:47:26 -070040class BitmapWrapper {
John Reckf29ed282015-04-07 07:32:03 -070041public:
sergeyvc1c54062016-10-19 18:47:26 -070042 BitmapWrapper(Bitmap* bitmap)
43 : mBitmap(bitmap) { }
sergeyvc69853c2016-10-07 14:14:09 -070044
45 void freePixels() {
sergeyvc1c54062016-10-19 18:47:26 -070046 mInfo = mBitmap->info();
47 mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
48 mAllocationSize = mBitmap->getAllocationByteCount();
49 mRowBytes = mBitmap->rowBytes();
50 mGenerationId = mBitmap->getGenerationID();
51 mBitmap.reset();
John Reckf29ed282015-04-07 07:32:03 -070052 }
53
sergeyvc69853c2016-10-07 14:14:09 -070054 bool valid() {
sergeyvfc9999502016-10-17 13:07:38 -070055 return mBitmap;
John Reckf29ed282015-04-07 07:32:03 -070056 }
57
sergeyvaed7f582016-10-14 16:30:21 -070058 Bitmap& bitmap() {
59 assertValid();
60 return *mBitmap;
61 }
sergeyvc69853c2016-10-07 14:14:09 -070062
63 void assertValid() {
64 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
65 }
66
67 void getSkBitmap(SkBitmap* outBitmap) {
68 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070069 mBitmap->getSkBitmap(outBitmap);
sergeyvc69853c2016-10-07 14:14:09 -070070 }
71
72 bool hasHardwareMipMap() {
sergeyvc1c54062016-10-19 18:47:26 -070073 if (mBitmap) {
74 return mBitmap->hasHardwareMipMap();
John Reckf29ed282015-04-07 07:32:03 -070075 }
John Reckf29ed282015-04-07 07:32:03 -070076 return mHasHardwareMipMap;
77 }
78
79 void setHasHardwareMipMap(bool hasMipMap) {
sergeyvc69853c2016-10-07 14:14:09 -070080 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070081 mBitmap->setHasHardwareMipMap(hasMipMap);
John Reckf29ed282015-04-07 07:32:03 -070082 }
83
sergeyvc69853c2016-10-07 14:14:09 -070084 void setAlphaType(SkAlphaType alphaType) {
85 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070086 mBitmap->setAlphaType(alphaType);
John Reckf29ed282015-04-07 07:32:03 -070087 }
88
sergeyvc69853c2016-10-07 14:14:09 -070089 const SkImageInfo& info() {
sergeyvc1c54062016-10-19 18:47:26 -070090 if (mBitmap) {
91 return mBitmap->info();
sergeyvc69853c2016-10-07 14:14:09 -070092 }
93 return mInfo;
John Reckf29ed282015-04-07 07:32:03 -070094 }
95
sergeyvc69853c2016-10-07 14:14:09 -070096 size_t getAllocationByteCount() const {
sergeyvc1c54062016-10-19 18:47:26 -070097 if (mBitmap) {
98 return mBitmap->getAllocationByteCount();
sergeyvc69853c2016-10-07 14:14:09 -070099 }
100 return mAllocationSize;
John Reckf29ed282015-04-07 07:32:03 -0700101 }
102
sergeyvc69853c2016-10-07 14:14:09 -0700103 size_t rowBytes() const {
sergeyvc1c54062016-10-19 18:47:26 -0700104 if (mBitmap) {
105 return mBitmap->rowBytes();
sergeyvc69853c2016-10-07 14:14:09 -0700106 }
107 return mRowBytes;
108 }
109
110 uint32_t getGenerationID() const {
sergeyvc1c54062016-10-19 18:47:26 -0700111 if (mBitmap) {
112 return mBitmap->getGenerationID();
sergeyvc69853c2016-10-07 14:14:09 -0700113 }
114 return mGenerationId;
115 }
116
sergeyvc1c54062016-10-19 18:47:26 -0700117 ~BitmapWrapper() { }
sergeyvc69853c2016-10-07 14:14:09 -0700118
John Reckf29ed282015-04-07 07:32:03 -0700119private:
sergeyvc1c54062016-10-19 18:47:26 -0700120 sk_sp<Bitmap> mBitmap;
sergeyvc69853c2016-10-07 14:14:09 -0700121 SkImageInfo mInfo;
122 bool mHasHardwareMipMap;
123 size_t mAllocationSize;
124 size_t mRowBytes;
125 uint32_t mGenerationId;
John Reckf29ed282015-04-07 07:32:03 -0700126};
127
John Reckf29ed282015-04-07 07:32:03 -0700128// Convenience class that does not take a global ref on the pixels, relying
129// on the caller already having a local JNI ref
130class LocalScopedBitmap {
131public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700132 explicit LocalScopedBitmap(jlong bitmapHandle)
sergeyvc1c54062016-10-19 18:47:26 -0700133 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
John Reckf29ed282015-04-07 07:32:03 -0700134
sergeyvc1c54062016-10-19 18:47:26 -0700135 BitmapWrapper* operator->() {
136 return mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700137 }
138
139 void* pixels() {
sergeyvaed7f582016-10-14 16:30:21 -0700140 return mBitmapWrapper->bitmap().pixels();
John Reckf29ed282015-04-07 07:32:03 -0700141 }
142
143 bool valid() {
sergeyvc1c54062016-10-19 18:47:26 -0700144 return mBitmapWrapper && mBitmapWrapper->valid();
John Reckf29ed282015-04-07 07:32:03 -0700145 }
146
147private:
sergeyvc1c54062016-10-19 18:47:26 -0700148 BitmapWrapper* mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700149};
150
sergeyvc69853c2016-10-07 14:14:09 -0700151namespace bitmap {
152
153// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
154static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
155 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
156 // irrelevant. This just tests to ensure that the SkAlphaType is not
157 // opposite of isPremultiplied.
158 if (isPremultiplied) {
159 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
160 } else {
161 SkASSERT(info.alphaType() != kPremul_SkAlphaType);
162 }
163}
164
165void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
166 bool isPremultiplied)
167{
168 // The caller needs to have already set the alpha type properly, so the
169 // native SkBitmap stays in sync with the Java Bitmap.
170 assert_premultiplied(info, isPremultiplied);
171
172 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
173 info.width(), info.height(), isPremultiplied);
174}
175
176int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
177{
178 return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
179}
180
sergeyvc1c54062016-10-19 18:47:26 -0700181jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
sergeyvc69853c2016-10-07 14:14:09 -0700182 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
183 int density) {
184 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
185 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
186 // The caller needs to have already set the alpha type properly, so the
187 // native SkBitmap stays in sync with the Java Bitmap.
sergeyvc1c54062016-10-19 18:47:26 -0700188 assert_premultiplied(bitmap->info(), isPremultiplied);
189 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
sergeyvc69853c2016-10-07 14:14:09 -0700190 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
sergeyvc1c54062016-10-19 18:47:26 -0700191 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
192 isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
sergeyvc69853c2016-10-07 14:14:09 -0700193
194 if (env->ExceptionCheck() != 0) {
195 ALOGE("*** Uncaught exception returned from Java call!\n");
196 env->ExceptionDescribe();
197 }
198 return obj;
199}
200
201void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
202 LocalScopedBitmap bitmap(bitmapHandle);
203 bitmap->getSkBitmap(outBitmap);
204}
205
sergeyvaed7f582016-10-14 16:30:21 -0700206Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700207 SkASSERT(env);
208 SkASSERT(bitmap);
209 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
210 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
211 LocalScopedBitmap localBitmap(bitmapHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700212 return localBitmap->bitmap();
sergeyvc69853c2016-10-07 14:14:09 -0700213}
214
sergeyv5fd2a1c2016-10-20 15:04:28 -0700215Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
216 SkASSERT(env);
217 LocalScopedBitmap localBitmap(bitmapHandle);
218 return localBitmap->bitmap();
219}
220
sergeyvc69853c2016-10-07 14:14:09 -0700221} // namespace bitmap
222
223} // namespace android
224
225using namespace android;
226using namespace android::bitmap;
227
Chris Craik32054b02014-05-09 13:58:56 -0700228///////////////////////////////////////////////////////////////////////////////
229// Conversions to/from SkColor, for get/setPixels, and the create method, which
230// is basically like setPixels
231
232typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
233 int x, int y);
234
235static void FromColor_D32(void* dst, const SkColor src[], int width,
236 int, int) {
237 SkPMColor* d = (SkPMColor*)dst;
238
239 for (int i = 0; i < width; i++) {
240 *d++ = SkPreMultiplyColor(*src++);
241 }
242}
243
244static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
245 int, int) {
Dan Albert46d84442014-11-18 16:07:51 -0800246 // Needed to thwart the unreachable code detection from clang.
247 static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
248
Chris Craik32054b02014-05-09 13:58:56 -0700249 // SkColor's ordering may be different from SkPMColor
Dan Albert46d84442014-11-18 16:07:51 -0800250 if (sk_color_ne_zero) {
Chris Craik32054b02014-05-09 13:58:56 -0700251 memcpy(dst, src, width * sizeof(SkColor));
252 return;
253 }
254
255 // order isn't same, repack each pixel manually
256 SkPMColor* d = (SkPMColor*)dst;
257 for (int i = 0; i < width; i++) {
258 SkColor c = *src++;
259 *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
260 SkColorGetG(c), SkColorGetB(c));
261 }
262}
263
264static void FromColor_D565(void* dst, const SkColor src[], int width,
265 int x, int y) {
266 uint16_t* d = (uint16_t*)dst;
267
268 DITHER_565_SCAN(y);
269 for (int stop = x + width; x < stop; x++) {
270 SkColor c = *src++;
271 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
272 DITHER_VALUE(x));
273 }
274}
275
276static void FromColor_D4444(void* dst, const SkColor src[], int width,
277 int x, int y) {
278 SkPMColor16* d = (SkPMColor16*)dst;
279
280 DITHER_4444_SCAN(y);
281 for (int stop = x + width; x < stop; x++) {
282 SkPMColor pmc = SkPreMultiplyColor(*src++);
283 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
284// *d++ = SkPixel32ToPixel4444(pmc);
285 }
286}
287
288static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
289 int x, int y) {
290 SkPMColor16* d = (SkPMColor16*)dst;
291
292 DITHER_4444_SCAN(y);
293 for (int stop = x + width; x < stop; x++) {
294 SkColor c = *src++;
295
296 // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
297 SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
298 SkColorGetG(c), SkColorGetB(c));
299 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
300// *d++ = SkPixel32ToPixel4444(pmc);
301 }
302}
303
Chris Craik6260b222015-07-24 15:17:29 -0700304static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
305 uint8_t* d = (uint8_t*)dst;
306
307 for (int stop = x + width; x < stop; x++) {
308 *d++ = SkColorGetA(*src++);
309 }
310}
311
Chris Craik32054b02014-05-09 13:58:56 -0700312// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400313static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
314 switch (bitmap.colorType()) {
315 case kN32_SkColorType:
316 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
317 case kARGB_4444_SkColorType:
318 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
319 FromColor_D4444_Raw;
320 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700321 return FromColor_D565;
Chris Craik6260b222015-07-24 15:17:29 -0700322 case kAlpha_8_SkColorType:
323 return FromColor_DA8;
Chris Craik32054b02014-05-09 13:58:56 -0700324 default:
325 break;
326 }
327 return NULL;
328}
329
330bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400331 int x, int y, int width, int height, const SkBitmap& dstBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700332 SkAutoLockPixels alp(dstBitmap);
333 void* dst = dstBitmap.getPixels();
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400334 FromColorProc proc = ChooseFromColorProc(dstBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700335
336 if (NULL == dst || NULL == proc) {
337 return false;
338 }
339
340 const jint* array = env->GetIntArrayElements(srcColors, NULL);
341 const SkColor* src = (const SkColor*)array + srcOffset;
342
343 // reset to to actual choice from caller
344 dst = dstBitmap.getAddr(x, y);
345 // now copy/convert each scanline
346 for (int y = 0; y < height; y++) {
347 proc(dst, src, width, x, y);
348 src += srcStride;
349 dst = (char*)dst + dstBitmap.rowBytes();
350 }
351
352 dstBitmap.notifyPixelsChanged();
353
354 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
355 JNI_ABORT);
356 return true;
357}
358
359//////////////////// ToColor procs
360
361typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
362 SkColorTable*);
363
364static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
365 SkColorTable*) {
366 SkASSERT(width > 0);
367 const SkPMColor* s = (const SkPMColor*)src;
368 do {
369 *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
370 } while (--width != 0);
371}
372
373static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
374 SkColorTable*) {
375 SkASSERT(width > 0);
376 const SkPMColor* s = (const SkPMColor*)src;
377 do {
378 SkPMColor c = *s++;
379 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
380 SkGetPackedG32(c), SkGetPackedB32(c));
381 } while (--width != 0);
382}
383
384static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
385 SkColorTable*) {
386 SkASSERT(width > 0);
387 const SkPMColor* s = (const SkPMColor*)src;
388 do {
389 SkPMColor c = *s++;
390 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
391 SkGetPackedB32(c));
392 } while (--width != 0);
393}
394
395static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
396 SkColorTable*) {
397 SkASSERT(width > 0);
398 const SkPMColor16* s = (const SkPMColor16*)src;
399 do {
400 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
401 } while (--width != 0);
402}
403
404static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
405 SkColorTable*) {
406 SkASSERT(width > 0);
407 const SkPMColor16* s = (const SkPMColor16*)src;
408 do {
409 SkPMColor c = SkPixel4444ToPixel32(*s++);
410 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
411 SkGetPackedG32(c), SkGetPackedB32(c));
412 } while (--width != 0);
413}
414
415static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
416 SkColorTable*) {
417 SkASSERT(width > 0);
418 const SkPMColor16* s = (const SkPMColor16*)src;
419 do {
420 SkPMColor c = SkPixel4444ToPixel32(*s++);
421 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
422 SkGetPackedB32(c));
423 } while (--width != 0);
424}
425
426static void ToColor_S565(SkColor dst[], const void* src, int width,
427 SkColorTable*) {
428 SkASSERT(width > 0);
429 const uint16_t* s = (const uint16_t*)src;
430 do {
431 uint16_t c = *s++;
432 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
433 SkPacked16ToB32(c));
434 } while (--width != 0);
435}
436
437static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
438 SkColorTable* ctable) {
439 SkASSERT(width > 0);
440 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500441 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700442 do {
443 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
444 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700445}
446
447static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
448 SkColorTable* ctable) {
449 SkASSERT(width > 0);
450 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500451 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700452 do {
453 SkPMColor c = colors[*s++];
454 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
455 SkGetPackedG32(c), SkGetPackedB32(c));
456 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700457}
458
459static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
460 SkColorTable* ctable) {
461 SkASSERT(width > 0);
462 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500463 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700464 do {
465 SkPMColor c = colors[*s++];
466 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
467 SkGetPackedB32(c));
468 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700469}
470
Chris Craik6260b222015-07-24 15:17:29 -0700471static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
472 SkASSERT(width > 0);
473 const uint8_t* s = (const uint8_t*)src;
474 do {
475 uint8_t c = *s++;
476 *dst++ = SkColorSetARGB(c, c, c, c);
477 } while (--width != 0);
478}
479
Chris Craik32054b02014-05-09 13:58:56 -0700480// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400481static ToColorProc ChooseToColorProc(const SkBitmap& src) {
Mike Reedb9330552014-06-16 17:31:48 -0400482 switch (src.colorType()) {
483 case kN32_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400484 switch (src.alphaType()) {
485 case kOpaque_SkAlphaType:
486 return ToColor_S32_Opaque;
487 case kPremul_SkAlphaType:
488 return ToColor_S32_Alpha;
489 case kUnpremul_SkAlphaType:
490 return ToColor_S32_Raw;
491 default:
492 return NULL;
493 }
Mike Reedb9330552014-06-16 17:31:48 -0400494 case kARGB_4444_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400495 switch (src.alphaType()) {
496 case kOpaque_SkAlphaType:
497 return ToColor_S4444_Opaque;
498 case kPremul_SkAlphaType:
499 return ToColor_S4444_Alpha;
500 case kUnpremul_SkAlphaType:
501 return ToColor_S4444_Raw;
502 default:
503 return NULL;
504 }
Mike Reedb9330552014-06-16 17:31:48 -0400505 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700506 return ToColor_S565;
Mike Reedb9330552014-06-16 17:31:48 -0400507 case kIndex_8_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700508 if (src.getColorTable() == NULL) {
509 return NULL;
510 }
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400511 switch (src.alphaType()) {
512 case kOpaque_SkAlphaType:
513 return ToColor_SI8_Opaque;
514 case kPremul_SkAlphaType:
515 return ToColor_SI8_Alpha;
516 case kUnpremul_SkAlphaType:
517 return ToColor_SI8_Raw;
518 default:
519 return NULL;
520 }
Chris Craik6260b222015-07-24 15:17:29 -0700521 case kAlpha_8_SkColorType:
522 return ToColor_SA8;
Chris Craik32054b02014-05-09 13:58:56 -0700523 default:
524 break;
525 }
526 return NULL;
527}
528
529///////////////////////////////////////////////////////////////////////////////
530///////////////////////////////////////////////////////////////////////////////
531
532static int getPremulBitmapCreateFlags(bool isMutable) {
sergeyvc69853c2016-10-07 14:14:09 -0700533 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
534 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
Chris Craik32054b02014-05-09 13:58:56 -0700535 return flags;
536}
537
538static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
539 jint offset, jint stride, jint width, jint height,
540 jint configHandle, jboolean isMutable) {
Mike Reed1103b322014-07-08 12:36:44 -0400541 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700542 if (NULL != jColors) {
543 size_t n = env->GetArrayLength(jColors);
544 if (n < SkAbs32(stride) * (size_t)height) {
545 doThrowAIOOBE(env);
546 return NULL;
547 }
548 }
549
550 // ARGB_4444 is a deprecated format, convert automatically to 8888
Mike Reedb9330552014-06-16 17:31:48 -0400551 if (colorType == kARGB_4444_SkColorType) {
552 colorType = kN32_SkColorType;
Chris Craik32054b02014-05-09 13:58:56 -0700553 }
554
555 SkBitmap bitmap;
Romain Guy253f2c22016-09-28 17:34:42 -0700556 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
557 GraphicsJNI::defaultColorSpace()));
Chris Craik32054b02014-05-09 13:58:56 -0700558
sergeyvc1c54062016-10-19 18:47:26 -0700559 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
John Reckf29ed282015-04-07 07:32:03 -0700560 if (!nativeBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700561 return NULL;
562 }
563
564 if (jColors != NULL) {
565 GraphicsJNI::SetPixels(env, jColors, offset, stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400566 0, 0, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700567 }
568
sergeyvc36bd6c2016-10-11 15:49:16 -0700569 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700570}
571
572static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
573 jint dstConfigHandle, jboolean isMutable) {
John Reckf29ed282015-04-07 07:32:03 -0700574 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700575 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Mike Reed1103b322014-07-08 12:36:44 -0400576 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyv45082182016-09-29 18:25:40 -0700577 SkBitmap result;
578 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700579
John Reckf29ed282015-04-07 07:32:03 -0700580 if (!src.copyTo(&result, dstCT, &allocator)) {
Chris Craik32054b02014-05-09 13:58:56 -0700581 return NULL;
582 }
sergeyvc1c54062016-10-19 18:47:26 -0700583 auto bitmap = allocator.getStorageObjAndReset();
584 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700585}
586
sergeyvc1c54062016-10-19 18:47:26 -0700587static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700588 SkBitmap result;
589
590 AshmemPixelAllocator allocator(env);
Winsona5fdde92016-04-14 15:27:15 -0700591 if (!src.copyTo(&result, dstCT, &allocator)) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700592 return NULL;
593 }
sergeyvc1c54062016-10-19 18:47:26 -0700594 auto bitmap = allocator.getStorageObjAndReset();
595 bitmap->setImmutable();
596 return bitmap;
Winsona5fdde92016-04-14 15:27:15 -0700597}
598
599static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
600 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700601 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700602 SkColorType dstCT = src.colorType();
sergeyvc1c54062016-10-19 18:47:26 -0700603 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
604 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Winsona5fdde92016-04-14 15:27:15 -0700605 return ret;
606}
607
608static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
609 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700610 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700611 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700612 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
613 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Riley Andrews721ae5f2015-05-11 16:08:22 -0700614 return ret;
615}
616
sergeyvc1c54062016-10-19 18:47:26 -0700617static void Bitmap_destruct(BitmapWrapper* bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700618 delete bitmap;
Chris Craik32054b02014-05-09 13:58:56 -0700619}
620
Richard Uhler775873a2015-12-29 12:37:39 -0800621static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
622 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
623}
624
Chris Craik32054b02014-05-09 13:58:56 -0700625static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700626 LocalScopedBitmap bitmap(bitmapHandle);
627 bitmap->freePixels();
Chris Craik32054b02014-05-09 13:58:56 -0700628 return JNI_TRUE;
629}
630
631static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
sergeyv45082182016-09-29 18:25:40 -0700632 jint width, jint height, jint configHandle, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700633 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700634 bitmap->assertValid();
Mike Reed1103b322014-07-08 12:36:44 -0400635 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400636
637 // ARGB_4444 is a deprecated format, convert automatically to 8888
638 if (colorType == kARGB_4444_SkColorType) {
639 colorType = kN32_SkColorType;
640 }
sergeyv45082182016-09-29 18:25:40 -0700641 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
642 if (requestedSize > bitmap->getAllocationByteCount()) {
Chris Craik32054b02014-05-09 13:58:56 -0700643 // done in native as there's no way to get BytesPerPixel in Java
644 doThrowIAE(env, "Bitmap not large enough to support new configuration");
645 return;
646 }
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400647 SkAlphaType alphaType;
John Reckf29ed282015-04-07 07:32:03 -0700648 if (bitmap->info().colorType() != kRGB_565_SkColorType
649 && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400650 // If the original bitmap was set to opaque, keep that setting, unless it
651 // was 565, which is required to be opaque.
652 alphaType = kOpaque_SkAlphaType;
653 } else {
654 // Otherwise respect the premultiplied request.
655 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
656 }
sergeyvaed7f582016-10-14 16:30:21 -0700657 bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
sergeyv7d5219f2016-11-03 16:18:16 -0700658 sk_ref_sp(bitmap->info().colorSpace())));
Chris Craik32054b02014-05-09 13:58:56 -0700659}
660
661// These must match the int values in Bitmap.java
662enum JavaEncodeFormat {
663 kJPEG_JavaEncodeFormat = 0,
664 kPNG_JavaEncodeFormat = 1,
665 kWEBP_JavaEncodeFormat = 2
666};
667
668static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
669 jint format, jint quality,
670 jobject jstream, jbyteArray jstorage) {
Hal Canary10219fb2016-11-23 20:41:22 -0500671 SkEncodedImageFormat fm;
Chris Craik32054b02014-05-09 13:58:56 -0700672 switch (format) {
673 case kJPEG_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500674 fm = SkEncodedImageFormat::kJPEG;
Chris Craik32054b02014-05-09 13:58:56 -0700675 break;
676 case kPNG_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500677 fm = SkEncodedImageFormat::kPNG;
Chris Craik32054b02014-05-09 13:58:56 -0700678 break;
679 case kWEBP_JavaEncodeFormat:
Hal Canary10219fb2016-11-23 20:41:22 -0500680 fm = SkEncodedImageFormat::kWEBP;
Chris Craik32054b02014-05-09 13:58:56 -0700681 break;
682 default:
683 return JNI_FALSE;
684 }
685
Hal Canary10219fb2016-11-23 20:41:22 -0500686 LocalScopedBitmap bitmap(bitmapHandle);
John Reckf29ed282015-04-07 07:32:03 -0700687 if (!bitmap.valid()) {
688 return JNI_FALSE;
689 }
690
John Reckf29ed282015-04-07 07:32:03 -0700691 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
692 if (!strm.get()) {
693 return JNI_FALSE;
694 }
Chris Craik32054b02014-05-09 13:58:56 -0700695
Hal Canary10219fb2016-11-23 20:41:22 -0500696 SkBitmap skbitmap;
697 bitmap->getSkBitmap(&skbitmap);
698 return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700699}
700
701static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
John Reckf29ed282015-04-07 07:32:03 -0700702 LocalScopedBitmap bitmap(bitmapHandle);
703 SkBitmap skBitmap;
704 bitmap->getSkBitmap(&skBitmap);
705 skBitmap.eraseColor(color);
Chris Craik32054b02014-05-09 13:58:56 -0700706}
707
708static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700709 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700710 return static_cast<jint>(bitmap->rowBytes());
711}
712
713static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700714 LocalScopedBitmap bitmap(bitmapHandle);
715 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
Chris Craik32054b02014-05-09 13:58:56 -0700716}
717
718static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700719 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700720 return static_cast<jint>(bitmap->getGenerationID());
Chris Craik32054b02014-05-09 13:58:56 -0700721}
722
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400723static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700724 LocalScopedBitmap bitmap(bitmapHandle);
725 if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400726 return JNI_TRUE;
727 }
728 return JNI_FALSE;
729}
730
Chris Craik32054b02014-05-09 13:58:56 -0700731static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700732 LocalScopedBitmap bitmap(bitmapHandle);
733 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700734}
735
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400736static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
737 jboolean hasAlpha, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700738 LocalScopedBitmap bitmap(bitmapHandle);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400739 if (hasAlpha) {
John Reck0781a2f2015-05-27 16:29:17 -0700740 bitmap->setAlphaType(
John Reckf29ed282015-04-07 07:32:03 -0700741 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
Chris Craik32054b02014-05-09 13:58:56 -0700742 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700743 bitmap->setAlphaType(kOpaque_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400744 }
745}
746
747static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
748 jboolean isPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700749 LocalScopedBitmap bitmap(bitmapHandle);
750 if (!bitmap->info().isOpaque()) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400751 if (isPremul) {
John Reck0781a2f2015-05-27 16:29:17 -0700752 bitmap->setAlphaType(kPremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400753 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700754 bitmap->setAlphaType(kUnpremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400755 }
Chris Craik32054b02014-05-09 13:58:56 -0700756 }
757}
758
759static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700760 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700761 return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
762}
763
764static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
765 jboolean hasMipMap) {
John Reckf29ed282015-04-07 07:32:03 -0700766 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700767 bitmap->setHasHardwareMipMap(hasMipMap);
768}
769
770///////////////////////////////////////////////////////////////////////////////
771
772static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
773 if (parcel == NULL) {
774 SkDebugf("-------- unparcel parcel is NULL\n");
775 return NULL;
776 }
777
778 android::Parcel* p = android::parcelForJavaObject(env, parcel);
779
Mike Reedb9330552014-06-16 17:31:48 -0400780 const bool isMutable = p->readInt32() != 0;
781 const SkColorType colorType = (SkColorType)p->readInt32();
782 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
Romain Guy253f2c22016-09-28 17:34:42 -0700783 const bool isSRGB = p->readInt32() != 0;
Mike Reedb9330552014-06-16 17:31:48 -0400784 const int width = p->readInt32();
785 const int height = p->readInt32();
786 const int rowBytes = p->readInt32();
787 const int density = p->readInt32();
Chris Craik32054b02014-05-09 13:58:56 -0700788
Mike Reedb9330552014-06-16 17:31:48 -0400789 if (kN32_SkColorType != colorType &&
790 kRGB_565_SkColorType != colorType &&
791 kARGB_4444_SkColorType != colorType &&
792 kIndex_8_SkColorType != colorType &&
793 kAlpha_8_SkColorType != colorType) {
794 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
Chris Craik32054b02014-05-09 13:58:56 -0700795 return NULL;
796 }
797
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400798 std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700799
Romain Guy253f2c22016-09-28 17:34:42 -0700800 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
Mike Reedab12c1f2016-11-03 12:54:10 -0400801 isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400802 return NULL;
803 }
Chris Craik32054b02014-05-09 13:58:56 -0700804
805 SkColorTable* ctable = NULL;
Mike Reedb9330552014-06-16 17:31:48 -0400806 if (colorType == kIndex_8_SkColorType) {
Chris Craik32054b02014-05-09 13:58:56 -0700807 int count = p->readInt32();
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400808 if (count < 0 || count > 256) {
809 // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
810 // inclusive.
811 return NULL;
812 }
Chris Craik32054b02014-05-09 13:58:56 -0700813 if (count > 0) {
814 size_t size = count * sizeof(SkPMColor);
815 const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400816 if (src == NULL) {
817 return NULL;
818 }
Chris Craik32054b02014-05-09 13:58:56 -0700819 ctable = new SkColorTable(src, count);
820 }
821 }
822
Jeff Browna316c5d2015-06-05 15:14:06 -0700823 // Read the bitmap blob.
824 size_t size = bitmap->getSize();
825 android::Parcel::ReadableBlob blob;
826 android::status_t status = p->readBlob(size, &blob);
827 if (status) {
Chris Craik32054b02014-05-09 13:58:56 -0700828 SkSafeUnref(ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700829 doThrowRE(env, "Could not read bitmap blob.");
Chris Craik32054b02014-05-09 13:58:56 -0700830 return NULL;
831 }
832
Jeff Browna316c5d2015-06-05 15:14:06 -0700833 // Map the bitmap in place from the ashmem region if possible otherwise copy.
sergeyvc1c54062016-10-19 18:47:26 -0700834 sk_sp<Bitmap> nativeBitmap;
Riley Andrews8cee7c12015-11-01 23:36:04 -0800835 if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700836#if DEBUG_PARCEL
837 ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
838 "(fds %s)",
839 isMutable ? "mutable" : "immutable",
840 blob.isMutable() ? "mutable" : "immutable",
841 p->allowFds() ? "allowed" : "forbidden");
842#endif
843 // Dup the file descriptor so we can keep a reference to it after the Parcel
844 // is disposed.
845 int dupFd = dup(blob.fd());
846 if (dupFd < 0) {
Erik Wolsheimer211abad2015-11-13 11:54:47 -0800847 ALOGE("Error allocating dup fd. Error:%d", errno);
Jeff Browna316c5d2015-06-05 15:14:06 -0700848 blob.release();
849 SkSafeUnref(ctable);
850 doThrowRE(env, "Could not allocate dup blob fd.");
851 return NULL;
852 }
853
854 // Map the pixels in place and take ownership of the ashmem region.
sergeyvc1c54062016-10-19 18:47:26 -0700855 nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
sergeyvc36bd6c2016-10-11 15:49:16 -0700856 ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
Jeff Browna316c5d2015-06-05 15:14:06 -0700857 SkSafeUnref(ctable);
858 if (!nativeBitmap) {
859 close(dupFd);
860 blob.release();
861 doThrowRE(env, "Could not allocate ashmem pixel ref.");
862 return NULL;
863 }
864
865 // Clear the blob handle, don't release it.
866 blob.clear();
867 } else {
868#if DEBUG_PARCEL
869 if (blob.fd() >= 0) {
870 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
871 "from immutable blob (fds %s)",
872 p->allowFds() ? "allowed" : "forbidden");
873 } else {
874 ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
875 "(fds %s)",
876 blob.isMutable() ? "mutable" : "immutable",
877 p->allowFds() ? "allowed" : "forbidden");
878 }
879#endif
880
881 // Copy the pixels into a new buffer.
sergeyvc1c54062016-10-19 18:47:26 -0700882 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700883 SkSafeUnref(ctable);
884 if (!nativeBitmap) {
885 blob.release();
886 doThrowRE(env, "Could not allocate java pixel ref.");
887 return NULL;
888 }
889 bitmap->lockPixels();
890 memcpy(bitmap->getPixels(), blob.data(), size);
891 bitmap->unlockPixels();
892
893 // Release the blob handle.
894 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700895 }
Chris Craik32054b02014-05-09 13:58:56 -0700896
sergeyvc36bd6c2016-10-11 15:49:16 -0700897 return createBitmap(env, nativeBitmap.release(),
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400898 getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
Chris Craik32054b02014-05-09 13:58:56 -0700899}
900
901static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
902 jlong bitmapHandle,
903 jboolean isMutable, jint density,
904 jobject parcel) {
Chris Craik32054b02014-05-09 13:58:56 -0700905 if (parcel == NULL) {
906 SkDebugf("------- writeToParcel null parcel\n");
907 return JNI_FALSE;
908 }
909
910 android::Parcel* p = android::parcelForJavaObject(env, parcel);
John Reckf29ed282015-04-07 07:32:03 -0700911 SkBitmap bitmap;
Riley Andrews39d7f302014-11-13 17:43:25 -0800912
sergeyvc1c54062016-10-19 18:47:26 -0700913 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
914 bitmapWrapper->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700915
Mike Reedab12c1f2016-11-03 12:54:10 -0400916 sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
Romain Guy253f2c22016-09-28 17:34:42 -0700917 bool isSRGB = bitmap.colorSpace() == sRGB.get();
918
Chris Craik32054b02014-05-09 13:58:56 -0700919 p->writeInt32(isMutable);
John Reckf29ed282015-04-07 07:32:03 -0700920 p->writeInt32(bitmap.colorType());
921 p->writeInt32(bitmap.alphaType());
Romain Guy253f2c22016-09-28 17:34:42 -0700922 p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
John Reckf29ed282015-04-07 07:32:03 -0700923 p->writeInt32(bitmap.width());
924 p->writeInt32(bitmap.height());
925 p->writeInt32(bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700926 p->writeInt32(density);
927
John Reckf29ed282015-04-07 07:32:03 -0700928 if (bitmap.colorType() == kIndex_8_SkColorType) {
Leon Scroggins III66ce1c32016-02-02 11:11:55 -0500929 // The bitmap needs to be locked to access its color table.
930 SkAutoLockPixels alp(bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700931 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -0700932 if (ctable != NULL) {
933 int count = ctable->count();
934 p->writeInt32(count);
935 memcpy(p->writeInplace(count * sizeof(SkPMColor)),
Mike Reed71487eb2014-11-19 16:13:20 -0500936 ctable->readColors(), count * sizeof(SkPMColor));
Chris Craik32054b02014-05-09 13:58:56 -0700937 } else {
938 p->writeInt32(0); // indicate no ctable
939 }
940 }
941
Jeff Browna316c5d2015-06-05 15:14:06 -0700942 // Transfer the underlying ashmem region if we have one and it's immutable.
943 android::status_t status;
sergeyvaed7f582016-10-14 16:30:21 -0700944 int fd = bitmapWrapper->bitmap().getAshmemFd();
Jeff Browna316c5d2015-06-05 15:14:06 -0700945 if (fd >= 0 && !isMutable && p->allowFds()) {
946#if DEBUG_PARCEL
947 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
948 "immutable blob (fds %s)",
949 p->allowFds() ? "allowed" : "forbidden");
950#endif
951
952 status = p->writeDupImmutableBlobFileDescriptor(fd);
953 if (status) {
954 doThrowRE(env, "Could not write bitmap blob file descriptor.");
Riley Andrews39d7f302014-11-13 17:43:25 -0800955 return JNI_FALSE;
956 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700957 return JNI_TRUE;
Riley Andrews39d7f302014-11-13 17:43:25 -0800958 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700959
960 // Copy the bitmap to a new blob.
961 bool mutableCopy = isMutable;
962#if DEBUG_PARCEL
963 ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
964 isMutable ? "mutable" : "immutable",
965 mutableCopy ? "mutable" : "immutable",
966 p->allowFds() ? "allowed" : "forbidden");
967#endif
968
969 size_t size = bitmap.getSize();
970 android::Parcel::WritableBlob blob;
971 status = p->writeBlob(size, mutableCopy, &blob);
972 if (status) {
973 doThrowRE(env, "Could not copy bitmap to parcel blob.");
974 return JNI_FALSE;
975 }
976
977 bitmap.lockPixels();
978 const void* pSrc = bitmap.getPixels();
979 if (pSrc == NULL) {
980 memset(blob.data(), 0, size);
981 } else {
982 memcpy(blob.data(), pSrc, size);
983 }
984 bitmap.unlockPixels();
985
986 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700987 return JNI_TRUE;
988}
989
990static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
991 jlong srcHandle, jlong paintHandle,
992 jintArray offsetXY) {
John Reckf29ed282015-04-07 07:32:03 -0700993 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700994 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -0400995 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700996 SkIPoint offset;
John Reckf29ed282015-04-07 07:32:03 -0700997 SkBitmap dst;
sergeyv45082182016-09-29 18:25:40 -0700998 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700999
John Reckf29ed282015-04-07 07:32:03 -07001000 src.extractAlpha(&dst, paint, &allocator, &offset);
Chris Craik32054b02014-05-09 13:58:56 -07001001 // If Skia can't allocate pixels for destination bitmap, it resets
1002 // it, that is set its pixels buffer to NULL, and zero width and height.
John Reckf29ed282015-04-07 07:32:03 -07001003 if (dst.getPixels() == NULL && src.getPixels() != NULL) {
Chris Craik32054b02014-05-09 13:58:56 -07001004 doThrowOOME(env, "failed to allocate pixels for alpha");
1005 return NULL;
1006 }
1007 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
1008 int* array = env->GetIntArrayElements(offsetXY, NULL);
1009 array[0] = offset.fX;
1010 array[1] = offset.fY;
1011 env->ReleaseIntArrayElements(offsetXY, array, 0);
1012 }
1013
sergeyvc69853c2016-10-07 14:14:09 -07001014 return createBitmap(env, allocator.getStorageObjAndReset(),
John Reckf29ed282015-04-07 07:32:03 -07001015 getPremulBitmapCreateFlags(true));
Chris Craik32054b02014-05-09 13:58:56 -07001016}
1017
1018///////////////////////////////////////////////////////////////////////////////
1019
1020static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001021 jint x, jint y) {
John Reckf29ed282015-04-07 07:32:03 -07001022 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001023 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001024 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001025
John Reckf29ed282015-04-07 07:32:03 -07001026 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001027 if (NULL == proc) {
1028 return 0;
1029 }
John Reckf29ed282015-04-07 07:32:03 -07001030 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001031 if (NULL == src) {
1032 return 0;
1033 }
1034
1035 SkColor dst[1];
John Reckf29ed282015-04-07 07:32:03 -07001036 proc(dst, src, 1, bitmap.getColorTable());
Chris Craik32054b02014-05-09 13:58:56 -07001037 return static_cast<jint>(dst[0]);
1038}
1039
1040static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1041 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001042 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001043 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001044 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001045 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001046
John Reckf29ed282015-04-07 07:32:03 -07001047 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001048 if (NULL == proc) {
1049 return;
1050 }
John Reckf29ed282015-04-07 07:32:03 -07001051 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001052 if (NULL == src) {
1053 return;
1054 }
1055
John Reckf29ed282015-04-07 07:32:03 -07001056 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001057 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
1058 SkColor* d = (SkColor*)dst + offset;
1059 while (--height >= 0) {
1060 proc(d, src, width, ctable);
1061 d += stride;
John Reckf29ed282015-04-07 07:32:03 -07001062 src = (void*)((const char*)src + bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -07001063 }
1064 env->ReleaseIntArrayElements(pixelArray, dst, 0);
1065}
1066
1067///////////////////////////////////////////////////////////////////////////////
1068
1069static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001070 jint x, jint y, jint colorHandle) {
John Reckf29ed282015-04-07 07:32:03 -07001071 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001072 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001073 SkColor color = static_cast<SkColor>(colorHandle);
John Reckf29ed282015-04-07 07:32:03 -07001074 SkAutoLockPixels alp(bitmap);
1075 if (NULL == bitmap.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001076 return;
1077 }
1078
John Reckf29ed282015-04-07 07:32:03 -07001079 FromColorProc proc = ChooseFromColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001080 if (NULL == proc) {
1081 return;
1082 }
1083
John Reckf29ed282015-04-07 07:32:03 -07001084 proc(bitmap.getAddr(x, y), &color, 1, x, y);
1085 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001086}
1087
1088static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1089 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001090 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001091 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001092 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001093 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
John Reckf29ed282015-04-07 07:32:03 -07001094 x, y, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001095}
1096
1097static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
1098 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001099 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001100 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001101 SkAutoLockPixels alp(bitmap);
1102 const void* src = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001103
1104 if (NULL != src) {
1105 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
1106
1107 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001108 memcpy(abp.pointer(), src, bitmap.getSize());
Chris Craik32054b02014-05-09 13:58:56 -07001109 }
1110}
1111
1112static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
1113 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001114 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001115 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001116 SkAutoLockPixels alp(bitmap);
1117 void* dst = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001118
1119 if (NULL != dst) {
1120 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
1121 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001122 memcpy(dst, abp.pointer(), bitmap.getSize());
1123 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001124 }
1125}
1126
1127static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
1128 jlong bm1Handle) {
John Reckf29ed282015-04-07 07:32:03 -07001129 SkBitmap bm0;
1130 SkBitmap bm1;
sergeyvc1c54062016-10-19 18:47:26 -07001131 reinterpret_cast<BitmapWrapper*>(bm0Handle)->getSkBitmap(&bm0);
1132 reinterpret_cast<BitmapWrapper*>(bm1Handle)->getSkBitmap(&bm1);
John Reckf29ed282015-04-07 07:32:03 -07001133 if (bm0.width() != bm1.width() ||
1134 bm0.height() != bm1.height() ||
Romain Guy253f2c22016-09-28 17:34:42 -07001135 bm0.colorType() != bm1.colorType() ||
1136 bm0.alphaType() != bm1.alphaType() ||
1137 bm0.colorSpace() != bm1.colorSpace()) {
Chris Craik32054b02014-05-09 13:58:56 -07001138 return JNI_FALSE;
1139 }
1140
John Reckf29ed282015-04-07 07:32:03 -07001141 SkAutoLockPixels alp0(bm0);
1142 SkAutoLockPixels alp1(bm1);
Chris Craik32054b02014-05-09 13:58:56 -07001143
1144 // if we can't load the pixels, return false
John Reckf29ed282015-04-07 07:32:03 -07001145 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001146 return JNI_FALSE;
1147 }
1148
John Reckf29ed282015-04-07 07:32:03 -07001149 if (bm0.colorType() == kIndex_8_SkColorType) {
1150 SkColorTable* ct0 = bm0.getColorTable();
1151 SkColorTable* ct1 = bm1.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001152 if (NULL == ct0 || NULL == ct1) {
1153 return JNI_FALSE;
1154 }
1155 if (ct0->count() != ct1->count()) {
1156 return JNI_FALSE;
1157 }
1158
Chris Craik32054b02014-05-09 13:58:56 -07001159 const size_t size = ct0->count() * sizeof(SkPMColor);
Mike Reed71487eb2014-11-19 16:13:20 -05001160 if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001161 return JNI_FALSE;
1162 }
1163 }
1164
1165 // now compare each scanline. We can't do the entire buffer at once,
1166 // since we don't care about the pixel values that might extend beyond
1167 // the width (since the scanline might be larger than the logical width)
John Reckf29ed282015-04-07 07:32:03 -07001168 const int h = bm0.height();
1169 const size_t size = bm0.width() * bm0.bytesPerPixel();
Chris Craik32054b02014-05-09 13:58:56 -07001170 for (int y = 0; y < h; y++) {
henry.uh_chen53001ca2014-07-03 20:40:22 +08001171 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1172 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1173 // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1174 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1175 // to warn user those 2 unrecognized config bitmaps may be different.
John Reckf29ed282015-04-07 07:32:03 -07001176 void *bm0Addr = bm0.getAddr(0, y);
1177 void *bm1Addr = bm1.getAddr(0, y);
henry.uh_chen53001ca2014-07-03 20:40:22 +08001178
1179 if(bm0Addr == NULL || bm1Addr == NULL) {
1180 return JNI_FALSE;
1181 }
1182
1183 if (memcmp(bm0Addr, bm1Addr, size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001184 return JNI_FALSE;
1185 }
1186 }
1187 return JNI_TRUE;
1188}
1189
John Reck43871902016-08-01 14:39:24 -07001190static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1191 LocalScopedBitmap bitmapHandle(bitmapPtr);
1192 if (!bitmapHandle.valid()) return;
sergeyvec4a4b12016-10-20 18:39:04 -07001193 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
John Reck43871902016-08-01 14:39:24 -07001194}
1195
sergeyv45082182016-09-29 18:25:40 -07001196static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1197 LocalScopedBitmap bitmapHandle(bitmapPtr);
1198 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1199}
1200
Chris Craik32054b02014-05-09 13:58:56 -07001201///////////////////////////////////////////////////////////////////////////////
sergeyvc69853c2016-10-07 14:14:09 -07001202static jclass make_globalref(JNIEnv* env, const char classname[])
1203{
1204 jclass c = env->FindClass(classname);
1205 SkASSERT(c);
1206 return (jclass) env->NewGlobalRef(c);
1207}
1208
1209static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1210 const char fieldname[], const char type[])
1211{
1212 jfieldID id = env->GetFieldID(clazz, fieldname, type);
1213 SkASSERT(id);
1214 return id;
1215}
Chris Craik32054b02014-05-09 13:58:56 -07001216
Daniel Micay76f6a862015-09-19 17:31:01 -04001217static const JNINativeMethod gBitmapMethods[] = {
Chris Craik32054b02014-05-09 13:58:56 -07001218 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
1219 (void*)Bitmap_creator },
1220 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1221 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001222 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1223 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001224 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1225 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001226 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Chris Craik32054b02014-05-09 13:58:56 -07001227 { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001228 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001229 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1230 (void*)Bitmap_compress },
1231 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
1232 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1233 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1234 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001235 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1236 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1237 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001238 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1239 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1240 { "nativeCreateFromParcel",
1241 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1242 (void*)Bitmap_createFromParcel },
1243 { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
1244 (void*)Bitmap_writeToParcel },
1245 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1246 (void*)Bitmap_extractAlpha },
1247 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001248 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
1249 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1250 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1251 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001252 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1253 (void*)Bitmap_copyPixelsToBuffer },
1254 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1255 (void*)Bitmap_copyPixelsFromBuffer },
1256 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
John Reck43871902016-08-01 14:39:24 -07001257 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001258 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
Chris Craik32054b02014-05-09 13:58:56 -07001259};
1260
Chris Craik32054b02014-05-09 13:58:56 -07001261int register_android_graphics_Bitmap(JNIEnv* env)
1262{
sergeyvc69853c2016-10-07 14:14:09 -07001263 gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1264 gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1265 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1266 gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1267 gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001268 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1269 NELEM(gBitmapMethods));
John Reck9192d5e2016-10-31 10:32:09 -07001270}