blob: 4a2f2878315383cbe29a7afe821a7bd652e60ed8 [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() {
sergeyvc1c54062016-10-19 18:47:26 -070055 return !!mBitmap;
John Reckf29ed282015-04-07 07:32:03 -070056 }
57
sergeyvc1c54062016-10-19 18:47:26 -070058 Bitmap* bitmap() { return mBitmap.get(); }
sergeyvc69853c2016-10-07 14:14:09 -070059
60 void assertValid() {
61 LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
62 }
63
64 void getSkBitmap(SkBitmap* outBitmap) {
65 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070066 mBitmap->getSkBitmap(outBitmap);
sergeyvc69853c2016-10-07 14:14:09 -070067 }
68
69 bool hasHardwareMipMap() {
sergeyvc1c54062016-10-19 18:47:26 -070070 if (mBitmap) {
71 return mBitmap->hasHardwareMipMap();
John Reckf29ed282015-04-07 07:32:03 -070072 }
John Reckf29ed282015-04-07 07:32:03 -070073 return mHasHardwareMipMap;
74 }
75
76 void setHasHardwareMipMap(bool hasMipMap) {
sergeyvc69853c2016-10-07 14:14:09 -070077 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070078 mBitmap->setHasHardwareMipMap(hasMipMap);
John Reckf29ed282015-04-07 07:32:03 -070079 }
80
sergeyvc69853c2016-10-07 14:14:09 -070081 void setAlphaType(SkAlphaType alphaType) {
82 assertValid();
sergeyvc1c54062016-10-19 18:47:26 -070083 mBitmap->setAlphaType(alphaType);
John Reckf29ed282015-04-07 07:32:03 -070084 }
85
sergeyvc69853c2016-10-07 14:14:09 -070086 const SkImageInfo& info() {
sergeyvc1c54062016-10-19 18:47:26 -070087 if (mBitmap) {
88 return mBitmap->info();
sergeyvc69853c2016-10-07 14:14:09 -070089 }
90 return mInfo;
John Reckf29ed282015-04-07 07:32:03 -070091 }
92
sergeyvc69853c2016-10-07 14:14:09 -070093 size_t getAllocationByteCount() const {
sergeyvc1c54062016-10-19 18:47:26 -070094 if (mBitmap) {
95 return mBitmap->getAllocationByteCount();
sergeyvc69853c2016-10-07 14:14:09 -070096 }
97 return mAllocationSize;
John Reckf29ed282015-04-07 07:32:03 -070098 }
99
sergeyvc69853c2016-10-07 14:14:09 -0700100 size_t rowBytes() const {
sergeyvc1c54062016-10-19 18:47:26 -0700101 if (mBitmap) {
102 return mBitmap->rowBytes();
sergeyvc69853c2016-10-07 14:14:09 -0700103 }
104 return mRowBytes;
105 }
106
107 uint32_t getGenerationID() const {
sergeyvc1c54062016-10-19 18:47:26 -0700108 if (mBitmap) {
109 return mBitmap->getGenerationID();
sergeyvc69853c2016-10-07 14:14:09 -0700110 }
111 return mGenerationId;
112 }
113
sergeyvc1c54062016-10-19 18:47:26 -0700114 ~BitmapWrapper() { }
sergeyvc69853c2016-10-07 14:14:09 -0700115
John Reckf29ed282015-04-07 07:32:03 -0700116private:
sergeyvc1c54062016-10-19 18:47:26 -0700117 sk_sp<Bitmap> mBitmap;
sergeyvc69853c2016-10-07 14:14:09 -0700118 SkImageInfo mInfo;
119 bool mHasHardwareMipMap;
120 size_t mAllocationSize;
121 size_t mRowBytes;
122 uint32_t mGenerationId;
John Reckf29ed282015-04-07 07:32:03 -0700123};
124
John Reckf29ed282015-04-07 07:32:03 -0700125// Convenience class that does not take a global ref on the pixels, relying
126// on the caller already having a local JNI ref
127class LocalScopedBitmap {
128public:
Chih-Hung Hsiehc6baf562016-04-27 11:29:23 -0700129 explicit LocalScopedBitmap(jlong bitmapHandle)
sergeyvc1c54062016-10-19 18:47:26 -0700130 : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
John Reckf29ed282015-04-07 07:32:03 -0700131
sergeyvc1c54062016-10-19 18:47:26 -0700132 BitmapWrapper* operator->() {
133 return mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700134 }
135
136 void* pixels() {
sergeyvc1c54062016-10-19 18:47:26 -0700137 return mBitmapWrapper->bitmap()->pixels();
John Reckf29ed282015-04-07 07:32:03 -0700138 }
139
140 bool valid() {
sergeyvc1c54062016-10-19 18:47:26 -0700141 return mBitmapWrapper && mBitmapWrapper->valid();
John Reckf29ed282015-04-07 07:32:03 -0700142 }
143
144private:
sergeyvc1c54062016-10-19 18:47:26 -0700145 BitmapWrapper* mBitmapWrapper;
John Reckf29ed282015-04-07 07:32:03 -0700146};
147
sergeyvc69853c2016-10-07 14:14:09 -0700148namespace bitmap {
149
150// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
151static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
152 // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
153 // irrelevant. This just tests to ensure that the SkAlphaType is not
154 // opposite of isPremultiplied.
155 if (isPremultiplied) {
156 SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
157 } else {
158 SkASSERT(info.alphaType() != kPremul_SkAlphaType);
159 }
160}
161
162void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
163 bool isPremultiplied)
164{
165 // The caller needs to have already set the alpha type properly, so the
166 // native SkBitmap stays in sync with the Java Bitmap.
167 assert_premultiplied(info, isPremultiplied);
168
169 env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
170 info.width(), info.height(), isPremultiplied);
171}
172
173int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
174{
175 return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
176}
177
sergeyvc1c54062016-10-19 18:47:26 -0700178jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
sergeyvc69853c2016-10-07 14:14:09 -0700179 int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
180 int density) {
181 bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
182 bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
183 // The caller needs to have already set the alpha type properly, so the
184 // native SkBitmap stays in sync with the Java Bitmap.
sergeyvc1c54062016-10-19 18:47:26 -0700185 assert_premultiplied(bitmap->info(), isPremultiplied);
186 BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
sergeyvc69853c2016-10-07 14:14:09 -0700187 jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
sergeyvc1c54062016-10-19 18:47:26 -0700188 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
189 isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
sergeyvc69853c2016-10-07 14:14:09 -0700190
191 if (env->ExceptionCheck() != 0) {
192 ALOGE("*** Uncaught exception returned from Java call!\n");
193 env->ExceptionDescribe();
194 }
195 return obj;
196}
197
198void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
199 LocalScopedBitmap bitmap(bitmapHandle);
200 bitmap->getSkBitmap(outBitmap);
201}
202
sergeyvc1c54062016-10-19 18:47:26 -0700203Bitmap* toBitmap(JNIEnv* env, jobject bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700204 SkASSERT(env);
205 SkASSERT(bitmap);
206 SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
207 jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
208 LocalScopedBitmap localBitmap(bitmapHandle);
209 localBitmap->assertValid();
sergeyvc1c54062016-10-19 18:47:26 -0700210 return localBitmap->bitmap();
sergeyvc69853c2016-10-07 14:14:09 -0700211}
212
213} // namespace bitmap
214
215} // namespace android
216
217using namespace android;
218using namespace android::bitmap;
219
Chris Craik32054b02014-05-09 13:58:56 -0700220///////////////////////////////////////////////////////////////////////////////
221// Conversions to/from SkColor, for get/setPixels, and the create method, which
222// is basically like setPixels
223
224typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
225 int x, int y);
226
227static void FromColor_D32(void* dst, const SkColor src[], int width,
228 int, int) {
229 SkPMColor* d = (SkPMColor*)dst;
230
231 for (int i = 0; i < width; i++) {
232 *d++ = SkPreMultiplyColor(*src++);
233 }
234}
235
236static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
237 int, int) {
Dan Albert46d84442014-11-18 16:07:51 -0800238 // Needed to thwart the unreachable code detection from clang.
239 static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
240
Chris Craik32054b02014-05-09 13:58:56 -0700241 // SkColor's ordering may be different from SkPMColor
Dan Albert46d84442014-11-18 16:07:51 -0800242 if (sk_color_ne_zero) {
Chris Craik32054b02014-05-09 13:58:56 -0700243 memcpy(dst, src, width * sizeof(SkColor));
244 return;
245 }
246
247 // order isn't same, repack each pixel manually
248 SkPMColor* d = (SkPMColor*)dst;
249 for (int i = 0; i < width; i++) {
250 SkColor c = *src++;
251 *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
252 SkColorGetG(c), SkColorGetB(c));
253 }
254}
255
256static void FromColor_D565(void* dst, const SkColor src[], int width,
257 int x, int y) {
258 uint16_t* d = (uint16_t*)dst;
259
260 DITHER_565_SCAN(y);
261 for (int stop = x + width; x < stop; x++) {
262 SkColor c = *src++;
263 *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
264 DITHER_VALUE(x));
265 }
266}
267
268static void FromColor_D4444(void* dst, const SkColor src[], int width,
269 int x, int y) {
270 SkPMColor16* d = (SkPMColor16*)dst;
271
272 DITHER_4444_SCAN(y);
273 for (int stop = x + width; x < stop; x++) {
274 SkPMColor pmc = SkPreMultiplyColor(*src++);
275 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
276// *d++ = SkPixel32ToPixel4444(pmc);
277 }
278}
279
280static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
281 int x, int y) {
282 SkPMColor16* d = (SkPMColor16*)dst;
283
284 DITHER_4444_SCAN(y);
285 for (int stop = x + width; x < stop; x++) {
286 SkColor c = *src++;
287
288 // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
289 SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
290 SkColorGetG(c), SkColorGetB(c));
291 *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
292// *d++ = SkPixel32ToPixel4444(pmc);
293 }
294}
295
Chris Craik6260b222015-07-24 15:17:29 -0700296static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
297 uint8_t* d = (uint8_t*)dst;
298
299 for (int stop = x + width; x < stop; x++) {
300 *d++ = SkColorGetA(*src++);
301 }
302}
303
Chris Craik32054b02014-05-09 13:58:56 -0700304// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400305static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
306 switch (bitmap.colorType()) {
307 case kN32_SkColorType:
308 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
309 case kARGB_4444_SkColorType:
310 return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
311 FromColor_D4444_Raw;
312 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700313 return FromColor_D565;
Chris Craik6260b222015-07-24 15:17:29 -0700314 case kAlpha_8_SkColorType:
315 return FromColor_DA8;
Chris Craik32054b02014-05-09 13:58:56 -0700316 default:
317 break;
318 }
319 return NULL;
320}
321
322bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400323 int x, int y, int width, int height, const SkBitmap& dstBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700324 SkAutoLockPixels alp(dstBitmap);
325 void* dst = dstBitmap.getPixels();
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400326 FromColorProc proc = ChooseFromColorProc(dstBitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700327
328 if (NULL == dst || NULL == proc) {
329 return false;
330 }
331
332 const jint* array = env->GetIntArrayElements(srcColors, NULL);
333 const SkColor* src = (const SkColor*)array + srcOffset;
334
335 // reset to to actual choice from caller
336 dst = dstBitmap.getAddr(x, y);
337 // now copy/convert each scanline
338 for (int y = 0; y < height; y++) {
339 proc(dst, src, width, x, y);
340 src += srcStride;
341 dst = (char*)dst + dstBitmap.rowBytes();
342 }
343
344 dstBitmap.notifyPixelsChanged();
345
346 env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
347 JNI_ABORT);
348 return true;
349}
350
351//////////////////// ToColor procs
352
353typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
354 SkColorTable*);
355
356static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
357 SkColorTable*) {
358 SkASSERT(width > 0);
359 const SkPMColor* s = (const SkPMColor*)src;
360 do {
361 *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
362 } while (--width != 0);
363}
364
365static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
366 SkColorTable*) {
367 SkASSERT(width > 0);
368 const SkPMColor* s = (const SkPMColor*)src;
369 do {
370 SkPMColor c = *s++;
371 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
372 SkGetPackedG32(c), SkGetPackedB32(c));
373 } while (--width != 0);
374}
375
376static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
377 SkColorTable*) {
378 SkASSERT(width > 0);
379 const SkPMColor* s = (const SkPMColor*)src;
380 do {
381 SkPMColor c = *s++;
382 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
383 SkGetPackedB32(c));
384 } while (--width != 0);
385}
386
387static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
388 SkColorTable*) {
389 SkASSERT(width > 0);
390 const SkPMColor16* s = (const SkPMColor16*)src;
391 do {
392 *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
393 } while (--width != 0);
394}
395
396static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
397 SkColorTable*) {
398 SkASSERT(width > 0);
399 const SkPMColor16* s = (const SkPMColor16*)src;
400 do {
401 SkPMColor c = SkPixel4444ToPixel32(*s++);
402 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
403 SkGetPackedG32(c), SkGetPackedB32(c));
404 } while (--width != 0);
405}
406
407static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
408 SkColorTable*) {
409 SkASSERT(width > 0);
410 const SkPMColor16* s = (const SkPMColor16*)src;
411 do {
412 SkPMColor c = SkPixel4444ToPixel32(*s++);
413 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
414 SkGetPackedB32(c));
415 } while (--width != 0);
416}
417
418static void ToColor_S565(SkColor dst[], const void* src, int width,
419 SkColorTable*) {
420 SkASSERT(width > 0);
421 const uint16_t* s = (const uint16_t*)src;
422 do {
423 uint16_t c = *s++;
424 *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
425 SkPacked16ToB32(c));
426 } while (--width != 0);
427}
428
429static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
430 SkColorTable* ctable) {
431 SkASSERT(width > 0);
432 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500433 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700434 do {
435 *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
436 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700437}
438
439static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
440 SkColorTable* ctable) {
441 SkASSERT(width > 0);
442 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500443 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700444 do {
445 SkPMColor c = colors[*s++];
446 *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
447 SkGetPackedG32(c), SkGetPackedB32(c));
448 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700449}
450
451static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
452 SkColorTable* ctable) {
453 SkASSERT(width > 0);
454 const uint8_t* s = (const uint8_t*)src;
Mike Reed71487eb2014-11-19 16:13:20 -0500455 const SkPMColor* colors = ctable->readColors();
Chris Craik32054b02014-05-09 13:58:56 -0700456 do {
457 SkPMColor c = colors[*s++];
458 *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
459 SkGetPackedB32(c));
460 } while (--width != 0);
Chris Craik32054b02014-05-09 13:58:56 -0700461}
462
Chris Craik6260b222015-07-24 15:17:29 -0700463static void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
464 SkASSERT(width > 0);
465 const uint8_t* s = (const uint8_t*)src;
466 do {
467 uint8_t c = *s++;
468 *dst++ = SkColorSetARGB(c, c, c, c);
469 } while (--width != 0);
470}
471
Chris Craik32054b02014-05-09 13:58:56 -0700472// can return NULL
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400473static ToColorProc ChooseToColorProc(const SkBitmap& src) {
Mike Reedb9330552014-06-16 17:31:48 -0400474 switch (src.colorType()) {
475 case kN32_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400476 switch (src.alphaType()) {
477 case kOpaque_SkAlphaType:
478 return ToColor_S32_Opaque;
479 case kPremul_SkAlphaType:
480 return ToColor_S32_Alpha;
481 case kUnpremul_SkAlphaType:
482 return ToColor_S32_Raw;
483 default:
484 return NULL;
485 }
Mike Reedb9330552014-06-16 17:31:48 -0400486 case kARGB_4444_SkColorType:
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400487 switch (src.alphaType()) {
488 case kOpaque_SkAlphaType:
489 return ToColor_S4444_Opaque;
490 case kPremul_SkAlphaType:
491 return ToColor_S4444_Alpha;
492 case kUnpremul_SkAlphaType:
493 return ToColor_S4444_Raw;
494 default:
495 return NULL;
496 }
Mike Reedb9330552014-06-16 17:31:48 -0400497 case kRGB_565_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700498 return ToColor_S565;
Mike Reedb9330552014-06-16 17:31:48 -0400499 case kIndex_8_SkColorType:
Chris Craik32054b02014-05-09 13:58:56 -0700500 if (src.getColorTable() == NULL) {
501 return NULL;
502 }
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400503 switch (src.alphaType()) {
504 case kOpaque_SkAlphaType:
505 return ToColor_SI8_Opaque;
506 case kPremul_SkAlphaType:
507 return ToColor_SI8_Alpha;
508 case kUnpremul_SkAlphaType:
509 return ToColor_SI8_Raw;
510 default:
511 return NULL;
512 }
Chris Craik6260b222015-07-24 15:17:29 -0700513 case kAlpha_8_SkColorType:
514 return ToColor_SA8;
Chris Craik32054b02014-05-09 13:58:56 -0700515 default:
516 break;
517 }
518 return NULL;
519}
520
521///////////////////////////////////////////////////////////////////////////////
522///////////////////////////////////////////////////////////////////////////////
523
524static int getPremulBitmapCreateFlags(bool isMutable) {
sergeyvc69853c2016-10-07 14:14:09 -0700525 int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
526 if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
Chris Craik32054b02014-05-09 13:58:56 -0700527 return flags;
528}
529
530static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
531 jint offset, jint stride, jint width, jint height,
532 jint configHandle, jboolean isMutable) {
Mike Reed1103b322014-07-08 12:36:44 -0400533 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700534 if (NULL != jColors) {
535 size_t n = env->GetArrayLength(jColors);
536 if (n < SkAbs32(stride) * (size_t)height) {
537 doThrowAIOOBE(env);
538 return NULL;
539 }
540 }
541
542 // ARGB_4444 is a deprecated format, convert automatically to 8888
Mike Reedb9330552014-06-16 17:31:48 -0400543 if (colorType == kARGB_4444_SkColorType) {
544 colorType = kN32_SkColorType;
Chris Craik32054b02014-05-09 13:58:56 -0700545 }
546
547 SkBitmap bitmap;
Romain Guy253f2c22016-09-28 17:34:42 -0700548 bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
549 GraphicsJNI::defaultColorSpace()));
Chris Craik32054b02014-05-09 13:58:56 -0700550
sergeyvc1c54062016-10-19 18:47:26 -0700551 sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
John Reckf29ed282015-04-07 07:32:03 -0700552 if (!nativeBitmap) {
Chris Craik32054b02014-05-09 13:58:56 -0700553 return NULL;
554 }
555
556 if (jColors != NULL) {
557 GraphicsJNI::SetPixels(env, jColors, offset, stride,
Leon Scroggins III57ee6202014-06-04 18:51:07 -0400558 0, 0, width, height, bitmap);
Chris Craik32054b02014-05-09 13:58:56 -0700559 }
560
sergeyvc36bd6c2016-10-11 15:49:16 -0700561 return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700562}
563
564static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
565 jint dstConfigHandle, jboolean isMutable) {
John Reckf29ed282015-04-07 07:32:03 -0700566 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700567 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Mike Reed1103b322014-07-08 12:36:44 -0400568 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyv45082182016-09-29 18:25:40 -0700569 SkBitmap result;
570 HeapAllocator allocator;
Chris Craik32054b02014-05-09 13:58:56 -0700571
John Reckf29ed282015-04-07 07:32:03 -0700572 if (!src.copyTo(&result, dstCT, &allocator)) {
Chris Craik32054b02014-05-09 13:58:56 -0700573 return NULL;
574 }
sergeyvc1c54062016-10-19 18:47:26 -0700575 auto bitmap = allocator.getStorageObjAndReset();
576 return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
Chris Craik32054b02014-05-09 13:58:56 -0700577}
578
sergeyvc1c54062016-10-19 18:47:26 -0700579static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700580 SkBitmap result;
581
582 AshmemPixelAllocator allocator(env);
Winsona5fdde92016-04-14 15:27:15 -0700583 if (!src.copyTo(&result, dstCT, &allocator)) {
Riley Andrews721ae5f2015-05-11 16:08:22 -0700584 return NULL;
585 }
sergeyvc1c54062016-10-19 18:47:26 -0700586 auto bitmap = allocator.getStorageObjAndReset();
587 bitmap->setImmutable();
588 return bitmap;
Winsona5fdde92016-04-14 15:27:15 -0700589}
590
591static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
592 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700593 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700594 SkColorType dstCT = src.colorType();
sergeyvc1c54062016-10-19 18:47:26 -0700595 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
596 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Winsona5fdde92016-04-14 15:27:15 -0700597 return ret;
598}
599
600static jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
601 SkBitmap src;
sergeyvc1c54062016-10-19 18:47:26 -0700602 reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
Winsona5fdde92016-04-14 15:27:15 -0700603 SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
sergeyvc1c54062016-10-19 18:47:26 -0700604 auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
605 jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
Riley Andrews721ae5f2015-05-11 16:08:22 -0700606 return ret;
607}
608
sergeyvc1c54062016-10-19 18:47:26 -0700609static void Bitmap_destruct(BitmapWrapper* bitmap) {
sergeyvc69853c2016-10-07 14:14:09 -0700610 delete bitmap;
Chris Craik32054b02014-05-09 13:58:56 -0700611}
612
Richard Uhler775873a2015-12-29 12:37:39 -0800613static jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
614 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
615}
616
Chris Craik32054b02014-05-09 13:58:56 -0700617static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
John Reckf29ed282015-04-07 07:32:03 -0700618 LocalScopedBitmap bitmap(bitmapHandle);
619 bitmap->freePixels();
Chris Craik32054b02014-05-09 13:58:56 -0700620 return JNI_TRUE;
621}
622
623static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
sergeyv45082182016-09-29 18:25:40 -0700624 jint width, jint height, jint configHandle, jboolean requestPremul) {
John Reckf29ed282015-04-07 07:32:03 -0700625 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc69853c2016-10-07 14:14:09 -0700626 bitmap->assertValid();
Mike Reed1103b322014-07-08 12:36:44 -0400627 SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400628
629 // ARGB_4444 is a deprecated format, convert automatically to 8888
630 if (colorType == kARGB_4444_SkColorType) {
631 colorType = kN32_SkColorType;
632 }
sergeyv45082182016-09-29 18:25:40 -0700633 size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
634 if (requestedSize > bitmap->getAllocationByteCount()) {
Chris Craik32054b02014-05-09 13:58:56 -0700635 // done in native as there's no way to get BytesPerPixel in Java
636 doThrowIAE(env, "Bitmap not large enough to support new configuration");
637 return;
638 }
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400639 SkAlphaType alphaType;
John Reckf29ed282015-04-07 07:32:03 -0700640 if (bitmap->info().colorType() != kRGB_565_SkColorType
641 && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
Leon Scroggins III17a8bfc2014-06-03 16:15:15 -0400642 // If the original bitmap was set to opaque, keep that setting, unless it
643 // was 565, which is required to be opaque.
644 alphaType = kOpaque_SkAlphaType;
645 } else {
646 // Otherwise respect the premultiplied request.
647 alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
648 }
sergeyvc1c54062016-10-19 18:47:26 -0700649 bitmap->bitmap()->reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
Romain Guy253f2c22016-09-28 17:34:42 -0700650 sk_sp<SkColorSpace>(bitmap->info().colorSpace())));
Chris Craik32054b02014-05-09 13:58:56 -0700651}
652
653// These must match the int values in Bitmap.java
654enum JavaEncodeFormat {
655 kJPEG_JavaEncodeFormat = 0,
656 kPNG_JavaEncodeFormat = 1,
657 kWEBP_JavaEncodeFormat = 2
658};
659
660static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
661 jint format, jint quality,
662 jobject jstream, jbyteArray jstorage) {
John Reckf29ed282015-04-07 07:32:03 -0700663
664 LocalScopedBitmap bitmap(bitmapHandle);
Chris Craik32054b02014-05-09 13:58:56 -0700665 SkImageEncoder::Type fm;
666
667 switch (format) {
668 case kJPEG_JavaEncodeFormat:
669 fm = SkImageEncoder::kJPEG_Type;
670 break;
671 case kPNG_JavaEncodeFormat:
672 fm = SkImageEncoder::kPNG_Type;
673 break;
674 case kWEBP_JavaEncodeFormat:
675 fm = SkImageEncoder::kWEBP_Type;
676 break;
677 default:
678 return JNI_FALSE;
679 }
680
John Reckf29ed282015-04-07 07:32:03 -0700681 if (!bitmap.valid()) {
682 return JNI_FALSE;
683 }
684
Chris Craik32054b02014-05-09 13:58:56 -0700685 bool success = false;
Chris Craik32054b02014-05-09 13:58:56 -0700686
John Reckf29ed282015-04-07 07:32:03 -0700687 std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
688 if (!strm.get()) {
689 return JNI_FALSE;
690 }
Chris Craik32054b02014-05-09 13:58:56 -0700691
John Reckf29ed282015-04-07 07:32:03 -0700692 std::unique_ptr<SkImageEncoder> encoder(SkImageEncoder::Create(fm));
693 if (encoder.get()) {
694 SkBitmap skbitmap;
695 bitmap->getSkBitmap(&skbitmap);
696 success = encoder->encodeStream(strm.get(), skbitmap, quality);
Chris Craik32054b02014-05-09 13:58:56 -0700697 }
698 return success ? JNI_TRUE : JNI_FALSE;
699}
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,
801 isSRGB ? SkColorSpace::NewNamed(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
Romain Guy253f2c22016-09-28 17:34:42 -0700916 sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
917 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;
sergeyvc1c54062016-10-19 18:47:26 -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
Romain Guy1158b6d2016-10-12 10:55:08 -07001190static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
1191 LocalScopedBitmap bitmap(bitmapHandle);
sergeyvc1c54062016-10-19 18:47:26 -07001192 SkPixelRef* pixelRef = bitmap->bitmap();
Romain Guy1158b6d2016-10-12 10:55:08 -07001193 SkSafeRef(pixelRef);
1194 return reinterpret_cast<jlong>(pixelRef);
1195}
1196
John Reck43871902016-08-01 14:39:24 -07001197static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
1198 LocalScopedBitmap bitmapHandle(bitmapPtr);
1199 if (!bitmapHandle.valid()) return;
1200 SkBitmap bitmap;
1201 bitmapHandle->getSkBitmap(&bitmap);
1202 android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmap);
1203}
1204
sergeyv45082182016-09-29 18:25:40 -07001205static jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
1206 LocalScopedBitmap bitmapHandle(bitmapPtr);
1207 return static_cast<jint>(bitmapHandle->getAllocationByteCount());
1208}
1209
Chris Craik32054b02014-05-09 13:58:56 -07001210///////////////////////////////////////////////////////////////////////////////
sergeyvc69853c2016-10-07 14:14:09 -07001211static jclass make_globalref(JNIEnv* env, const char classname[])
1212{
1213 jclass c = env->FindClass(classname);
1214 SkASSERT(c);
1215 return (jclass) env->NewGlobalRef(c);
1216}
1217
1218static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1219 const char fieldname[], const char type[])
1220{
1221 jfieldID id = env->GetFieldID(clazz, fieldname, type);
1222 SkASSERT(id);
1223 return id;
1224}
Chris Craik32054b02014-05-09 13:58:56 -07001225
Daniel Micay76f6a862015-09-19 17:31:01 -04001226static const JNINativeMethod gBitmapMethods[] = {
Chris Craik32054b02014-05-09 13:58:56 -07001227 { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
1228 (void*)Bitmap_creator },
1229 { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
1230 (void*)Bitmap_copy },
Riley Andrews721ae5f2015-05-11 16:08:22 -07001231 { "nativeCopyAshmem", "(J)Landroid/graphics/Bitmap;",
1232 (void*)Bitmap_copyAshmem },
Winsona5fdde92016-04-14 15:27:15 -07001233 { "nativeCopyAshmemConfig", "(JI)Landroid/graphics/Bitmap;",
1234 (void*)Bitmap_copyAshmemConfig },
Richard Uhler775873a2015-12-29 12:37:39 -08001235 { "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
Chris Craik32054b02014-05-09 13:58:56 -07001236 { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
sergeyv45082182016-09-29 18:25:40 -07001237 { "nativeReconfigure", "(JIIIZ)V", (void*)Bitmap_reconfigure },
Chris Craik32054b02014-05-09 13:58:56 -07001238 { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
1239 (void*)Bitmap_compress },
1240 { "nativeErase", "(JI)V", (void*)Bitmap_erase },
1241 { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
1242 { "nativeConfig", "(J)I", (void*)Bitmap_config },
1243 { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001244 { "nativeIsPremultiplied", "(J)Z", (void*)Bitmap_isPremultiplied},
1245 { "nativeSetHasAlpha", "(JZZ)V", (void*)Bitmap_setHasAlpha},
1246 { "nativeSetPremultiplied", "(JZ)V", (void*)Bitmap_setPremultiplied},
Chris Craik32054b02014-05-09 13:58:56 -07001247 { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
1248 { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
1249 { "nativeCreateFromParcel",
1250 "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
1251 (void*)Bitmap_createFromParcel },
1252 { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
1253 (void*)Bitmap_writeToParcel },
1254 { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
1255 (void*)Bitmap_extractAlpha },
1256 { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
Leon Scroggins III57ee6202014-06-04 18:51:07 -04001257 { "nativeGetPixel", "(JII)I", (void*)Bitmap_getPixel },
1258 { "nativeGetPixels", "(J[IIIIIII)V", (void*)Bitmap_getPixels },
1259 { "nativeSetPixel", "(JIII)V", (void*)Bitmap_setPixel },
1260 { "nativeSetPixels", "(J[IIIIIII)V", (void*)Bitmap_setPixels },
Chris Craik32054b02014-05-09 13:58:56 -07001261 { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
1262 (void*)Bitmap_copyPixelsToBuffer },
1263 { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
1264 (void*)Bitmap_copyPixelsFromBuffer },
1265 { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
Romain Guy1158b6d2016-10-12 10:55:08 -07001266 { "nativeRefPixelRef", "(J)J", (void*)Bitmap_refPixelRef },
John Reck43871902016-08-01 14:39:24 -07001267 { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
sergeyv45082182016-09-29 18:25:40 -07001268 { "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
Chris Craik32054b02014-05-09 13:58:56 -07001269};
1270
Chris Craik32054b02014-05-09 13:58:56 -07001271int register_android_graphics_Bitmap(JNIEnv* env)
1272{
sergeyvc69853c2016-10-07 14:14:09 -07001273 gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1274 gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1275 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1276 gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1277 gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001278 return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1279 NELEM(gBitmapMethods));
sergeyvc69853c2016-10-07 14:14:09 -07001280}