blob: a489421bd7edf05951b516281d09341b6b1f6f96 [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,
Romain Guy253f2c22016-09-28 17:34:42 -0700658 sk_sp<SkColorSpace>(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) {
John Reckf29ed282015-04-07 07:32:03 -0700671
672 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700673 SkImageEncoder::Type fm;
674
675 switch (format) {
676 case kJPEG_JavaEncodeFormat:
677 fm = SkImageEncoder::kJPEG_Type;
678 break;
679 case kPNG_JavaEncodeFormat:
680 fm = SkImageEncoder::kPNG_Type;
681 break;
682 case kWEBP_JavaEncodeFormat:
683 fm = SkImageEncoder::kWEBP_Type;
684 break;
685 default:
686 return JNI_FALSE;
687 }
688
John Reckf29ed282015-04-07 07:32:03 -0700689 if (!bitmap.valid()) {
690 return JNI_FALSE;
691 }
692
Chris Craik32054b02014-05-09 13:58:56 -0700693 bool success = false;
Chris Craik32054b02014-05-09 13:58:56 -0700694
John Reckf29ed282015-04-07 07:32:03 -0700695 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
696 if (!strm.get()) {
697 return JNI_FALSE;
698 }
Chris Craik32054b02014-05-09 13:58:56 -0700699
John Reckf29ed282015-04-07 07:32:03 -0700700 std::unique_ptr<SkImageEncoder> encoder(SkImageEncoder::Create(fm));
701 if (encoder.get()) {
702 SkBitmap skbitmap;
703 bitmap->getSkBitmap(&skbitmap);
704 success = encoder->encodeStream(strm.get(), skbitmap, quality);
Chris Craik32054b02014-05-09 13:58:56 -0700705 }
706 return success ? JNI_TRUE : JNI_FALSE;
707}
708
709static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
John Reckf29ed282015-04-07 07:32:03 -0700710 LocalScopedBitmap bitmap(bitmapHandle);
711 SkBitmap skBitmap;
712 bitmap->getSkBitmap(&skBitmap);
713 skBitmap.eraseColor(color);
Chris Craik32054b02014-05-09 13:58:56 -0700714}
715
716static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700717 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700718 return static_cast<jint>(bitmap->rowBytes());
719}
720
721static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700722 LocalScopedBitmap bitmap(bitmapHandle);
723 return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
Chris Craik32054b02014-05-09 13:58:56 -0700724}
725
726static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700727 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700728 return static_cast<jint>(bitmap->getGenerationID());
Chris Craik32054b02014-05-09 13:58:56 -0700729}
730
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400731static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700732 LocalScopedBitmap bitmap(bitmapHandle);
733 if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400734 return JNI_TRUE;
735 }
736 return JNI_FALSE;
737}
738
Chris Craik32054b02014-05-09 13:58:56 -0700739static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700740 LocalScopedBitmap bitmap(bitmapHandle);
741 return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
Chris Craik32054b02014-05-09 13:58:56 -0700742}
743
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400744static void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
745 jboolean hasAlpha, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700746 LocalScopedBitmap bitmap(bitmapHandle);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400747 if (hasAlpha) {
John Reck0781a2f2015-05-27 16:29:17 -0700748 bitmap->setAlphaType(
John Reckf29ed282015-04-07 07:32:03 -0700749 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
Chris Craik32054b02014-05-09 13:58:56 -0700750 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700751 bitmap->setAlphaType(kOpaque_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400752 }
753}
754
755static void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
756 jboolean isPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700757 LocalScopedBitmap bitmap(bitmapHandle);
758 if (!bitmap->info().isOpaque()) {
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400759 if (isPremul) {
John Reck0781a2f2015-05-27 16:29:17 -0700760 bitmap->setAlphaType(kPremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400761 } else {
John Reck0781a2f2015-05-27 16:29:17 -0700762 bitmap->setAlphaType(kUnpremul_SkAlphaType);
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400763 }
Chris Craik32054b02014-05-09 13:58:56 -0700764 }
765}
766
767static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700768 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700769 return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
770}
771
772static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
773 jboolean hasMipMap) {
John Reckf29ed282015-04-07 07:32:03 -0700774 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700775 bitmap->setHasHardwareMipMap(hasMipMap);
776}
777
778///////////////////////////////////////////////////////////////////////////////
779
780static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
781 if (parcel == NULL) {
782 SkDebugf("-------- unparcel parcel is NULL\n");
783 return NULL;
784 }
785
786 android::Parcel* p = android::parcelForJavaObject(env, parcel);
787
Mike Reedb9330552014-06-16 17:31:48 -0400788 const bool isMutable = p->readInt32() != 0;
789 const SkColorType colorType = (SkColorType)p->readInt32();
790 const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
Romain Guy253f2c22016-09-28 17:34:42 -0700791 const bool isSRGB = p->readInt32() != 0;
Mike Reedb9330552014-06-16 17:31:48 -0400792 const int width = p->readInt32();
793 const int height = p->readInt32();
794 const int rowBytes = p->readInt32();
795 const int density = p->readInt32();
Chris Craik32054b02014-05-09 13:58:56 -0700796
Mike Reedb9330552014-06-16 17:31:48 -0400797 if (kN32_SkColorType != colorType &&
798 kRGB_565_SkColorType != colorType &&
799 kARGB_4444_SkColorType != colorType &&
800 kIndex_8_SkColorType != colorType &&
801 kAlpha_8_SkColorType != colorType) {
802 SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
Chris Craik32054b02014-05-09 13:58:56 -0700803 return NULL;
804 }
805
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400806 std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700807
Romain Guy253f2c22016-09-28 17:34:42 -0700808 if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
Mike Reedab12c1f2016-11-03 12:54:10 -0400809 isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400810 return NULL;
811 }
Chris Craik32054b02014-05-09 13:58:56 -0700812
813 SkColorTable* ctable = NULL;
Mike Reedb9330552014-06-16 17:31:48 -0400814 if (colorType == kIndex_8_SkColorType) {
Chris Craik32054b02014-05-09 13:58:56 -0700815 int count = p->readInt32();
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400816 if (count < 0 || count > 256) {
817 // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
818 // inclusive.
819 return NULL;
820 }
Chris Craik32054b02014-05-09 13:58:56 -0700821 if (count > 0) {
822 size_t size = count * sizeof(SkPMColor);
823 const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400824 if (src == NULL) {
825 return NULL;
826 }
Chris Craik32054b02014-05-09 13:58:56 -0700827 ctable = new SkColorTable(src, count);
828 }
829 }
830
Jeff Browna316c5d2015-06-05 15:14:06 -0700831 // Read the bitmap blob.
832 size_t size = bitmap->getSize();
833 android::Parcel::ReadableBlob blob;
834 android::status_t status = p->readBlob(size, &blob);
835 if (status) {
Chris Craik32054b02014-05-09 13:58:56 -0700836 SkSafeUnref(ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700837 doThrowRE(env, "Could not read bitmap blob.");
Chris Craik32054b02014-05-09 13:58:56 -0700838 return NULL;
839 }
840
Jeff Browna316c5d2015-06-05 15:14:06 -0700841 // Map the bitmap in place from the ashmem region if possible otherwise copy.
sergeyvc1c54062016-10-19 18:47:26 -0700842 sk_sp<Bitmap> nativeBitmap;
Riley Andrews8cee7c12015-11-01 23:36:04 -0800843 if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
Jeff Browna316c5d2015-06-05 15:14:06 -0700844#if DEBUG_PARCEL
845 ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
846 "(fds %s)",
847 isMutable ? "mutable" : "immutable",
848 blob.isMutable() ? "mutable" : "immutable",
849 p->allowFds() ? "allowed" : "forbidden");
850#endif
851 // Dup the file descriptor so we can keep a reference to it after the Parcel
852 // is disposed.
853 int dupFd = dup(blob.fd());
854 if (dupFd < 0) {
Erik Wolsheimer211abad2015-11-13 11:54:47 -0800855 ALOGE("Error allocating dup fd. Error:%d", errno);
Jeff Browna316c5d2015-06-05 15:14:06 -0700856 blob.release();
857 SkSafeUnref(ctable);
858 doThrowRE(env, "Could not allocate dup blob fd.");
859 return NULL;
860 }
861
862 // Map the pixels in place and take ownership of the ashmem region.
sergeyvc1c54062016-10-19 18:47:26 -0700863 nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
sergeyvc36bd6c2016-10-11 15:49:16 -0700864 ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
Jeff Browna316c5d2015-06-05 15:14:06 -0700865 SkSafeUnref(ctable);
866 if (!nativeBitmap) {
867 close(dupFd);
868 blob.release();
869 doThrowRE(env, "Could not allocate ashmem pixel ref.");
870 return NULL;
871 }
872
873 // Clear the blob handle, don't release it.
874 blob.clear();
875 } else {
876#if DEBUG_PARCEL
877 if (blob.fd() >= 0) {
878 ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
879 "from immutable blob (fds %s)",
880 p->allowFds() ? "allowed" : "forbidden");
881 } else {
882 ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
883 "(fds %s)",
884 blob.isMutable() ? "mutable" : "immutable",
885 p->allowFds() ? "allowed" : "forbidden");
886 }
887#endif
888
889 // Copy the pixels into a new buffer.
sergeyvc1c54062016-10-19 18:47:26 -0700890 nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
Jeff Browna316c5d2015-06-05 15:14:06 -0700891 SkSafeUnref(ctable);
892 if (!nativeBitmap) {
893 blob.release();
894 doThrowRE(env, "Could not allocate java pixel ref.");
895 return NULL;
896 }
897 bitmap->lockPixels();
898 memcpy(bitmap->getPixels(), blob.data(), size);
899 bitmap->unlockPixels();
900
901 // Release the blob handle.
902 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700903 }
Chris Craik32054b02014-05-09 13:58:56 -0700904
sergeyvc36bd6c2016-10-11 15:49:16 -0700905 return createBitmap(env, nativeBitmap.release(),
Leon Scroggins IIIec419e02015-03-11 13:12:06 -0400906 getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
Chris Craik32054b02014-05-09 13:58:56 -0700907}
908
909static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
910 jlong bitmapHandle,
911 jboolean isMutable, jint density,
912 jobject parcel) {
Chris Craik32054b02014-05-09 13:58:56 -0700913 if (parcel == NULL) {
914 SkDebugf("------- writeToParcel null parcel\n");
915 return JNI_FALSE;
916 }
917
918 android::Parcel* p = android::parcelForJavaObject(env, parcel);
John Reckf29ed282015-04-07 07:32:03 -0700919 SkBitmap bitmap;
Riley Andrews39d7f302014-11-13 17:43:25 -0800920
sergeyvc1c54062016-10-19 18:47:26 -0700921 auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
922 bitmapWrapper->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700923
Mike Reedab12c1f2016-11-03 12:54:10 -0400924 sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
Romain Guy253f2c22016-09-28 17:34:42 -0700925 bool isSRGB = bitmap.colorSpace() == sRGB.get();
926
Chris Craik32054b02014-05-09 13:58:56 -0700927 p->writeInt32(isMutable);
John Reckf29ed282015-04-07 07:32:03 -0700928 p->writeInt32(bitmap.colorType());
929 p->writeInt32(bitmap.alphaType());
Romain Guy253f2c22016-09-28 17:34:42 -0700930 p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
John Reckf29ed282015-04-07 07:32:03 -0700931 p->writeInt32(bitmap.width());
932 p->writeInt32(bitmap.height());
933 p->writeInt32(bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -0700934 p->writeInt32(density);
935
John Reckf29ed282015-04-07 07:32:03 -0700936 if (bitmap.colorType() == kIndex_8_SkColorType) {
Leon Scroggins III66ce1c32016-02-02 11:11:55 -0500937 // The bitmap needs to be locked to access its color table.
938 SkAutoLockPixels alp(bitmap);
John Reckf29ed282015-04-07 07:32:03 -0700939 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -0700940 if (ctable != NULL) {
941 int count = ctable->count();
942 p->writeInt32(count);
943 memcpy(p->writeInplace(count * sizeof(SkPMColor)),
Mike Reed71487eb2014-11-19 16:13:20 -0500944 ctable->readColors(), count * sizeof(SkPMColor));
Chris Craik32054b02014-05-09 13:58:56 -0700945 } else {
946 p->writeInt32(0); // indicate no ctable
947 }
948 }
949
Jeff Browna316c5d2015-06-05 15:14:06 -0700950 // Transfer the underlying ashmem region if we have one and it's immutable.
951 android::status_t status;
sergeyvaed7f582016-10-14 16:30:21 -0700952 int fd = bitmapWrapper->bitmap().getAshmemFd();
Jeff Browna316c5d2015-06-05 15:14:06 -0700953 if (fd >= 0 && !isMutable && p->allowFds()) {
954#if DEBUG_PARCEL
955 ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
956 "immutable blob (fds %s)",
957 p->allowFds() ? "allowed" : "forbidden");
958#endif
959
960 status = p->writeDupImmutableBlobFileDescriptor(fd);
961 if (status) {
962 doThrowRE(env, "Could not write bitmap blob file descriptor.");
Riley Andrews39d7f302014-11-13 17:43:25 -0800963 return JNI_FALSE;
964 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700965 return JNI_TRUE;
Riley Andrews39d7f302014-11-13 17:43:25 -0800966 }
Jeff Browna316c5d2015-06-05 15:14:06 -0700967
968 // Copy the bitmap to a new blob.
969 bool mutableCopy = isMutable;
970#if DEBUG_PARCEL
971 ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
972 isMutable ? "mutable" : "immutable",
973 mutableCopy ? "mutable" : "immutable",
974 p->allowFds() ? "allowed" : "forbidden");
975#endif
976
977 size_t size = bitmap.getSize();
978 android::Parcel::WritableBlob blob;
979 status = p->writeBlob(size, mutableCopy, &blob);
980 if (status) {
981 doThrowRE(env, "Could not copy bitmap to parcel blob.");
982 return JNI_FALSE;
983 }
984
985 bitmap.lockPixels();
986 const void* pSrc = bitmap.getPixels();
987 if (pSrc == NULL) {
988 memset(blob.data(), 0, size);
989 } else {
990 memcpy(blob.data(), pSrc, size);
991 }
992 bitmap.unlockPixels();
993
994 blob.release();
Chris Craik32054b02014-05-09 13:58:56 -0700995 return JNI_TRUE;
996}
997
998static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
999 jlong srcHandle, jlong paintHandle,
1000 jintArray offsetXY) {
John Reckf29ed282015-04-07 07:32:03 -07001001 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -07001002 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Behdad Esfahbod6ba30b82014-07-15 16:22:32 -04001003 const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
Chris Craik32054b02014-05-09 13:58:56 -07001004 SkIPoint offset;
John Reckf29ed282015-04-07 07:32:03 -07001005 SkBitmap dst;
sergeyv45082182016-09-29 18:25:40 -07001006 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -07001007
John Reckf29ed282015-04-07 07:32:03 -07001008 src.extractAlpha(&dst, paint, &allocator, &offset);
Chris Craik32054b02014-05-09 13:58:56 -07001009 // If Skia can't allocate pixels for destination bitmap, it resets
1010 // it, that is set its pixels buffer to NULL, and zero width and height.
John Reckf29ed282015-04-07 07:32:03 -07001011 if (dst.getPixels() == NULL && src.getPixels() != NULL) {
Chris Craik32054b02014-05-09 13:58:56 -07001012 doThrowOOME(env, "failed to allocate pixels for alpha");
1013 return NULL;
1014 }
1015 if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
1016 int* array = env->GetIntArrayElements(offsetXY, NULL);
1017 array[0] = offset.fX;
1018 array[1] = offset.fY;
1019 env->ReleaseIntArrayElements(offsetXY, array, 0);
1020 }
1021
sergeyvc69853c2016-10-07 14:14:09 -07001022 return createBitmap(env, allocator.getStorageObjAndReset(),
John Reckf29ed282015-04-07 07:32:03 -07001023 getPremulBitmapCreateFlags(true));
Chris Craik32054b02014-05-09 13:58:56 -07001024}
1025
1026///////////////////////////////////////////////////////////////////////////////
1027
1028static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001029 jint x, jint y) {
John Reckf29ed282015-04-07 07:32:03 -07001030 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001031 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001032 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001033
John Reckf29ed282015-04-07 07:32:03 -07001034 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001035 if (NULL == proc) {
1036 return 0;
1037 }
John Reckf29ed282015-04-07 07:32:03 -07001038 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001039 if (NULL == src) {
1040 return 0;
1041 }
1042
1043 SkColor dst[1];
John Reckf29ed282015-04-07 07:32:03 -07001044 proc(dst, src, 1, bitmap.getColorTable());
Chris Craik32054b02014-05-09 13:58:56 -07001045 return static_cast<jint>(dst[0]);
1046}
1047
1048static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1049 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001050 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001051 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001052 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001053 SkAutoLockPixels alp(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001054
John Reckf29ed282015-04-07 07:32:03 -07001055 ToColorProc proc = ChooseToColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001056 if (NULL == proc) {
1057 return;
1058 }
John Reckf29ed282015-04-07 07:32:03 -07001059 const void* src = bitmap.getAddr(x, y);
Chris Craik32054b02014-05-09 13:58:56 -07001060 if (NULL == src) {
1061 return;
1062 }
1063
John Reckf29ed282015-04-07 07:32:03 -07001064 SkColorTable* ctable = bitmap.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001065 jint* dst = env->GetIntArrayElements(pixelArray, NULL);
1066 SkColor* d = (SkColor*)dst + offset;
1067 while (--height >= 0) {
1068 proc(d, src, width, ctable);
1069 d += stride;
John Reckf29ed282015-04-07 07:32:03 -07001070 src = (void*)((const char*)src + bitmap.rowBytes());
Chris Craik32054b02014-05-09 13:58:56 -07001071 }
1072 env->ReleaseIntArrayElements(pixelArray, dst, 0);
1073}
1074
1075///////////////////////////////////////////////////////////////////////////////
1076
1077static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001078 jint x, jint y, jint colorHandle) {
John Reckf29ed282015-04-07 07:32:03 -07001079 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001080 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001081 SkColor color = static_cast<SkColor>(colorHandle);
John Reckf29ed282015-04-07 07:32:03 -07001082 SkAutoLockPixels alp(bitmap);
1083 if (NULL == bitmap.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001084 return;
1085 }
1086
John Reckf29ed282015-04-07 07:32:03 -07001087 FromColorProc proc = ChooseFromColorProc(bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001088 if (NULL == proc) {
1089 return;
1090 }
1091
John Reckf29ed282015-04-07 07:32:03 -07001092 proc(bitmap.getAddr(x, y), &color, 1, x, y);
1093 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001094}
1095
1096static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
1097 jintArray pixelArray, jint offset, jint stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001098 jint x, jint y, jint width, jint height) {
John Reckf29ed282015-04-07 07:32:03 -07001099 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001100 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001101 GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
John Reckf29ed282015-04-07 07:32:03 -07001102 x, y, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -07001103}
1104
1105static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
1106 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001107 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001108 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001109 SkAutoLockPixels alp(bitmap);
1110 const void* src = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001111
1112 if (NULL != src) {
1113 android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
1114
1115 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001116 memcpy(abp.pointer(), src, bitmap.getSize());
Chris Craik32054b02014-05-09 13:58:56 -07001117 }
1118}
1119
1120static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
1121 jlong bitmapHandle, jobject jbuffer) {
John Reckf29ed282015-04-07 07:32:03 -07001122 SkBitmap bitmap;
sergeyvc1c54062016-10-19 18:47:26 -07001123 reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
John Reckf29ed282015-04-07 07:32:03 -07001124 SkAutoLockPixels alp(bitmap);
1125 void* dst = bitmap.getPixels();
Chris Craik32054b02014-05-09 13:58:56 -07001126
1127 if (NULL != dst) {
1128 android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
1129 // the java side has already checked that buffer is large enough
John Reckf29ed282015-04-07 07:32:03 -07001130 memcpy(dst, abp.pointer(), bitmap.getSize());
1131 bitmap.notifyPixelsChanged();
Chris Craik32054b02014-05-09 13:58:56 -07001132 }
1133}
1134
1135static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
1136 jlong bm1Handle) {
John Reckf29ed282015-04-07 07:32:03 -07001137 SkBitmap bm0;
1138 SkBitmap bm1;
sergeyvc1c54062016-10-19 18:47:26 -07001139 reinterpret_cast<BitmapWrapper*>(bm0Handle)->getSkBitmap(&bm0);
1140 reinterpret_cast<BitmapWrapper*>(bm1Handle)->getSkBitmap(&bm1);
John Reckf29ed282015-04-07 07:32:03 -07001141 if (bm0.width() != bm1.width() ||
1142 bm0.height() != bm1.height() ||
Romain Guy253f2c22016-09-28 17:34:42 -07001143 bm0.colorType() != bm1.colorType() ||
1144 bm0.alphaType() != bm1.alphaType() ||
1145 bm0.colorSpace() != bm1.colorSpace()) {
Chris Craik32054b02014-05-09 13:58:56 -07001146 return JNI_FALSE;
1147 }
1148
John Reckf29ed282015-04-07 07:32:03 -07001149 SkAutoLockPixels alp0(bm0);
1150 SkAutoLockPixels alp1(bm1);
Chris Craik32054b02014-05-09 13:58:56 -07001151
1152 // if we can't load the pixels, return false
John Reckf29ed282015-04-07 07:32:03 -07001153 if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
Chris Craik32054b02014-05-09 13:58:56 -07001154 return JNI_FALSE;
1155 }
1156
John Reckf29ed282015-04-07 07:32:03 -07001157 if (bm0.colorType() == kIndex_8_SkColorType) {
1158 SkColorTable* ct0 = bm0.getColorTable();
1159 SkColorTable* ct1 = bm1.getColorTable();
Chris Craik32054b02014-05-09 13:58:56 -07001160 if (NULL == ct0 || NULL == ct1) {
1161 return JNI_FALSE;
1162 }
1163 if (ct0->count() != ct1->count()) {
1164 return JNI_FALSE;
1165 }
1166
Chris Craik32054b02014-05-09 13:58:56 -07001167 const size_t size = ct0->count() * sizeof(SkPMColor);
Mike Reed71487eb2014-11-19 16:13:20 -05001168 if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001169 return JNI_FALSE;
1170 }
1171 }
1172
1173 // now compare each scanline. We can't do the entire buffer at once,
1174 // since we don't care about the pixel values that might extend beyond
1175 // the width (since the scanline might be larger than the logical width)
John Reckf29ed282015-04-07 07:32:03 -07001176 const int h = bm0.height();
1177 const size_t size = bm0.width() * bm0.bytesPerPixel();
Chris Craik32054b02014-05-09 13:58:56 -07001178 for (int y = 0; y < h; y++) {
henry.uh_chen53001ca2014-07-03 20:40:22 +08001179 // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
1180 // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
1181 // and bm1 both have pixel data() (have passed NULL == getPixels() check),
1182 // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
1183 // to warn user those 2 unrecognized config bitmaps may be different.
John Reckf29ed282015-04-07 07:32:03 -07001184 void *bm0Addr = bm0.getAddr(0, y);
1185 void *bm1Addr = bm1.getAddr(0, y);
henry.uh_chen53001ca2014-07-03 20:40:22 +08001186
1187 if(bm0Addr == NULL || bm1Addr == NULL) {
1188 return JNI_FALSE;
1189 }
1190
1191 if (memcmp(bm0Addr, bm1Addr, size) != 0) {
Chris Craik32054b02014-05-09 13:58:56 -07001192 return JNI_FALSE;
1193 }
1194 }
1195 return JNI_TRUE;
1196}
1197
John Reck43871902016-08-01 14:39:24 -07001198static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1199 LocalScopedBitmap bitmapHandle(bitmapPtr);
1200 if (!bitmapHandle.valid()) return;
sergeyvec4a4b12016-10-20 18:39:04 -07001201 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
John Reck43871902016-08-01 14:39:24 -07001202}
1203
sergeyv45082182016-09-29 18:25:40 -07001204static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1205 LocalScopedBitmap bitmapHandle(bitmapPtr);
1206 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1207}
1208
Chris Craik32054b02014-05-09 13:58:56 -07001209///////////////////////////////////////////////////////////////////////////////
sergeyvc69853c2016-10-07 14:14:09 -07001210static jclass make_globalref(JNIEnv* env, const char classname[])
1211{
1212 jclass c = env->FindClass(classname);
1213 SkASSERT(c);
1214 return (jclass) env->NewGlobalRef(c);
1215}
1216
1217static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1218 const char fieldname[], const char type[])
1219{
1220 jfieldID id = env->GetFieldID(clazz, fieldname, type);
1221 SkASSERT(id);
1222 return id;
1223}
Chris Craik32054b02014-05-09 13:58:56 -07001224
Daniel Micay76f6a862015-09-19 17:31:01 -04001225static const JNINativeMethod gBitmapMethods[] = {
Chris Craik32054b02014-05-09 13:58:56 -07001226 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
1227 (void*)Bitmap_creator },
1228 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1229 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001230 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1231 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001232 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1233 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001234 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Chris Craik32054b02014-05-09 13:58:56 -07001235 { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001236 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001237 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1238 (void*)Bitmap_compress },
1239 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
1240 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1241 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1242 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001243 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1244 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1245 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001246 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1247 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1248 { "nativeCreateFromParcel",
1249 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1250 (void*)Bitmap_createFromParcel },
1251 { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
1252 (void*)Bitmap_writeToParcel },
1253 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1254 (void*)Bitmap_extractAlpha },
1255 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001256 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
1257 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1258 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1259 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001260 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1261 (void*)Bitmap_copyPixelsToBuffer },
1262 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1263 (void*)Bitmap_copyPixelsFromBuffer },
1264 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
John Reck43871902016-08-01 14:39:24 -07001265 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001266 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
Chris Craik32054b02014-05-09 13:58:56 -07001267};
1268
Chris Craik32054b02014-05-09 13:58:56 -07001269int register_android_graphics_Bitmap(JNIEnv* env)
1270{
sergeyvc69853c2016-10-07 14:14:09 -07001271 gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1272 gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1273 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1274 gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1275 gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001276 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1277 NELEM(gBitmapMethods));
John Reck9192d5e2016-10-31 10:32:09 -07001278}