Fix Bitmap.cpp line endings
Change-Id: Icc0b067437fffaa599c92841518ad0d526112f59
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e0fa9ba4..0328517 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1,838 +1,838 @@
-#include "SkBitmap.h"
-#include "SkPixelRef.h"
-#include "SkImageEncoder.h"
-#include "SkColorPriv.h"
-#include "GraphicsJNI.h"
-#include "SkDither.h"
-#include "SkUnPreMultiply.h"
-#include "SkStream.h"
-
-#include <binder/Parcel.h>
-#include "android_os_Parcel.h"
-#include "android_util_Binder.h"
-#include "android_nio_utils.h"
-#include "CreateJavaOutputStreamAdaptor.h"
-
-#include <jni.h>
-
-#include <Caches.h>
-
-#if 0
- #define TRACE_BITMAP(code) code
-#else
- #define TRACE_BITMAP(code)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Conversions to/from SkColor, for get/setPixels, and the create method, which
-// is basically like setPixels
-
-typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
- int x, int y);
-
-static void FromColor_D32(void* dst, const SkColor src[], int width,
- int, int) {
- SkPMColor* d = (SkPMColor*)dst;
-
- for (int i = 0; i < width; i++) {
- *d++ = SkPreMultiplyColor(*src++);
- }
-}
-
-static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
- int, int) {
- // SkColor's ordering may be different from SkPMColor
- if (SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER) {
- memcpy(dst, src, width * sizeof(SkColor));
- return;
- }
-
- // order isn't same, repack each pixel manually
- SkPMColor* d = (SkPMColor*)dst;
- for (int i = 0; i < width; i++) {
- SkColor c = *src++;
- *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
- SkColorGetG(c), SkColorGetB(c));
- }
-}
-
-static void FromColor_D565(void* dst, const SkColor src[], int width,
- int x, int y) {
- uint16_t* d = (uint16_t*)dst;
-
- DITHER_565_SCAN(y);
- for (int stop = x + width; x < stop; x++) {
- SkColor c = *src++;
- *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
- DITHER_VALUE(x));
- }
-}
-
-static void FromColor_D4444(void* dst, const SkColor src[], int width,
- int x, int y) {
- SkPMColor16* d = (SkPMColor16*)dst;
-
- DITHER_4444_SCAN(y);
- for (int stop = x + width; x < stop; x++) {
- SkPMColor pmc = SkPreMultiplyColor(*src++);
- *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
-// *d++ = SkPixel32ToPixel4444(pmc);
- }
-}
-
-static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
- int x, int y) {
- SkPMColor16* d = (SkPMColor16*)dst;
-
- DITHER_4444_SCAN(y);
- for (int stop = x + width; x < stop; x++) {
- SkColor c = *src++;
-
- // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
- SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
- SkColorGetG(c), SkColorGetB(c));
- *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
-// *d++ = SkPixel32ToPixel4444(pmc);
- }
-}
-
-// can return NULL
-static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremultiplied) {
- switch (config) {
- case SkBitmap::kARGB_8888_Config:
- return isPremultiplied ? FromColor_D32 : FromColor_D32_Raw;
- case SkBitmap::kARGB_4444_Config:
- return isPremultiplied ? FromColor_D4444 : FromColor_D4444_Raw;
- case SkBitmap::kRGB_565_Config:
- return FromColor_D565;
- default:
- break;
- }
- return NULL;
-}
-
-bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
- int x, int y, int width, int height,
- const SkBitmap& dstBitmap, bool isPremultiplied) {
- SkAutoLockPixels alp(dstBitmap);
- void* dst = dstBitmap.getPixels();
- FromColorProc proc = ChooseFromColorProc(dstBitmap.config(), isPremultiplied);
-
- if (NULL == dst || NULL == proc) {
- return false;
- }
-
- const jint* array = env->GetIntArrayElements(srcColors, NULL);
- const SkColor* src = (const SkColor*)array + srcOffset;
-
- // reset to to actual choice from caller
- dst = dstBitmap.getAddr(x, y);
- // now copy/convert each scanline
- for (int y = 0; y < height; y++) {
- proc(dst, src, width, x, y);
- src += srcStride;
- dst = (char*)dst + dstBitmap.rowBytes();
- }
-
- dstBitmap.notifyPixelsChanged();
-
- env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
- JNI_ABORT);
- return true;
-}
-
-//////////////////// ToColor procs
-
-typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
- SkColorTable*);
-
-static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
- SkColorTable*) {
- SkASSERT(width > 0);
- const SkPMColor* s = (const SkPMColor*)src;
- do {
- *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
- } while (--width != 0);
-}
-
-static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
- SkColorTable*) {
- SkASSERT(width > 0);
- const SkPMColor* s = (const SkPMColor*)src;
- do {
- SkPMColor c = *s++;
- *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
- SkGetPackedG32(c), SkGetPackedB32(c));
- } while (--width != 0);
-}
-
-static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
- SkColorTable*) {
- SkASSERT(width > 0);
- const SkPMColor* s = (const SkPMColor*)src;
- do {
- SkPMColor c = *s++;
- *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
- SkGetPackedB32(c));
- } while (--width != 0);
-}
-
-static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
- SkColorTable*) {
- SkASSERT(width > 0);
- const SkPMColor16* s = (const SkPMColor16*)src;
- do {
- *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
- } while (--width != 0);
-}
-
-static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
- SkColorTable*) {
- SkASSERT(width > 0);
- const SkPMColor16* s = (const SkPMColor16*)src;
- do {
- SkPMColor c = SkPixel4444ToPixel32(*s++);
- *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
- SkGetPackedG32(c), SkGetPackedB32(c));
- } while (--width != 0);
-}
-
-static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
- SkColorTable*) {
- SkASSERT(width > 0);
- const SkPMColor16* s = (const SkPMColor16*)src;
- do {
- SkPMColor c = SkPixel4444ToPixel32(*s++);
- *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
- SkGetPackedB32(c));
- } while (--width != 0);
-}
-
-static void ToColor_S565(SkColor dst[], const void* src, int width,
- SkColorTable*) {
- SkASSERT(width > 0);
- const uint16_t* s = (const uint16_t*)src;
- do {
- uint16_t c = *s++;
- *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
- SkPacked16ToB32(c));
- } while (--width != 0);
-}
-
-static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
- SkColorTable* ctable) {
- SkASSERT(width > 0);
- const uint8_t* s = (const uint8_t*)src;
- const SkPMColor* colors = ctable->lockColors();
- do {
- *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
- } while (--width != 0);
- ctable->unlockColors();
-}
-
-static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
- SkColorTable* ctable) {
- SkASSERT(width > 0);
- const uint8_t* s = (const uint8_t*)src;
- const SkPMColor* colors = ctable->lockColors();
- do {
- SkPMColor c = colors[*s++];
- *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
- SkGetPackedG32(c), SkGetPackedB32(c));
- } while (--width != 0);
- ctable->unlockColors();
-}
-
-static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
- SkColorTable* ctable) {
- SkASSERT(width > 0);
- const uint8_t* s = (const uint8_t*)src;
- const SkPMColor* colors = ctable->lockColors();
- do {
- SkPMColor c = colors[*s++];
- *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
- SkGetPackedB32(c));
- } while (--width != 0);
- ctable->unlockColors();
-}
-
-// can return NULL
-static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {
- switch (src.config()) {
- case SkBitmap::kARGB_8888_Config:
- if (src.isOpaque()) return ToColor_S32_Opaque;
- return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;
- case SkBitmap::kARGB_4444_Config:
- if (src.isOpaque()) return ToColor_S4444_Opaque;
- return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;
- case SkBitmap::kRGB_565_Config:
- return ToColor_S565;
- case SkBitmap::kIndex8_Config:
- if (src.getColorTable() == NULL) {
- return NULL;
- }
- if (src.isOpaque()) return ToColor_SI8_Opaque;
- return isPremultiplied ? ToColor_SI8_Raw : ToColor_SI8_Alpha;
- default:
- break;
- }
- return NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-static int getPremulBitmapCreateFlags(bool isMutable) {
- int flags = GraphicsJNI::kBitmapCreateFlag_Premultiplied;
- if (isMutable) flags |= GraphicsJNI::kBitmapCreateFlag_Mutable;
- return flags;
-}
-
-static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
- jint offset, jint stride, jint width, jint height,
- jint configHandle, jboolean isMutable) {
- SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
- if (NULL != jColors) {
- size_t n = env->GetArrayLength(jColors);
- if (n < SkAbs32(stride) * (size_t)height) {
- doThrowAIOOBE(env);
- return NULL;
- }
- }
-
- // ARGB_4444 is a deprecated format, convert automatically to 8888
- if (config == SkBitmap::kARGB_4444_Config) {
- config = SkBitmap::kARGB_8888_Config;
- }
-
- SkBitmap bitmap;
- bitmap.setConfig(config, width, height);
-
- jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
- if (NULL == buff) {
- return NULL;
- }
-
- if (jColors != NULL) {
- GraphicsJNI::SetPixels(env, jColors, offset, stride,
- 0, 0, width, height, bitmap, true);
- }
-
- return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
- getPremulBitmapCreateFlags(isMutable), NULL, NULL);
-}
-
-static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
- jint dstConfigHandle, jboolean isMutable) {
- const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
- SkBitmap::Config dstConfig = static_cast<SkBitmap::Config>(dstConfigHandle);
- SkBitmap result;
- JavaPixelAllocator allocator(env);
-
+#include "SkBitmap.h"
+#include "SkPixelRef.h"
+#include "SkImageEncoder.h"
+#include "SkColorPriv.h"
+#include "GraphicsJNI.h"
+#include "SkDither.h"
+#include "SkUnPreMultiply.h"
+#include "SkStream.h"
+
+#include <binder/Parcel.h>
+#include "android_os_Parcel.h"
+#include "android_util_Binder.h"
+#include "android_nio_utils.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+#include <jni.h>
+
+#include <Caches.h>
+
+#if 0
+ #define TRACE_BITMAP(code) code
+#else
+ #define TRACE_BITMAP(code)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Conversions to/from SkColor, for get/setPixels, and the create method, which
+// is basically like setPixels
+
+typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
+ int x, int y);
+
+static void FromColor_D32(void* dst, const SkColor src[], int width,
+ int, int) {
+ SkPMColor* d = (SkPMColor*)dst;
+
+ for (int i = 0; i < width; i++) {
+ *d++ = SkPreMultiplyColor(*src++);
+ }
+}
+
+static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
+ int, int) {
+ // SkColor's ordering may be different from SkPMColor
+ if (SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER) {
+ memcpy(dst, src, width * sizeof(SkColor));
+ return;
+ }
+
+ // order isn't same, repack each pixel manually
+ SkPMColor* d = (SkPMColor*)dst;
+ for (int i = 0; i < width; i++) {
+ SkColor c = *src++;
+ *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
+ SkColorGetG(c), SkColorGetB(c));
+ }
+}
+
+static void FromColor_D565(void* dst, const SkColor src[], int width,
+ int x, int y) {
+ uint16_t* d = (uint16_t*)dst;
+
+ DITHER_565_SCAN(y);
+ for (int stop = x + width; x < stop; x++) {
+ SkColor c = *src++;
+ *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
+ DITHER_VALUE(x));
+ }
+}
+
+static void FromColor_D4444(void* dst, const SkColor src[], int width,
+ int x, int y) {
+ SkPMColor16* d = (SkPMColor16*)dst;
+
+ DITHER_4444_SCAN(y);
+ for (int stop = x + width; x < stop; x++) {
+ SkPMColor pmc = SkPreMultiplyColor(*src++);
+ *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
+// *d++ = SkPixel32ToPixel4444(pmc);
+ }
+}
+
+static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
+ int x, int y) {
+ SkPMColor16* d = (SkPMColor16*)dst;
+
+ DITHER_4444_SCAN(y);
+ for (int stop = x + width; x < stop; x++) {
+ SkColor c = *src++;
+
+ // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
+ SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
+ SkColorGetG(c), SkColorGetB(c));
+ *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
+// *d++ = SkPixel32ToPixel4444(pmc);
+ }
+}
+
+// can return NULL
+static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremultiplied) {
+ switch (config) {
+ case SkBitmap::kARGB_8888_Config:
+ return isPremultiplied ? FromColor_D32 : FromColor_D32_Raw;
+ case SkBitmap::kARGB_4444_Config:
+ return isPremultiplied ? FromColor_D4444 : FromColor_D4444_Raw;
+ case SkBitmap::kRGB_565_Config:
+ return FromColor_D565;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
+ int x, int y, int width, int height,
+ const SkBitmap& dstBitmap, bool isPremultiplied) {
+ SkAutoLockPixels alp(dstBitmap);
+ void* dst = dstBitmap.getPixels();
+ FromColorProc proc = ChooseFromColorProc(dstBitmap.config(), isPremultiplied);
+
+ if (NULL == dst || NULL == proc) {
+ return false;
+ }
+
+ const jint* array = env->GetIntArrayElements(srcColors, NULL);
+ const SkColor* src = (const SkColor*)array + srcOffset;
+
+ // reset to to actual choice from caller
+ dst = dstBitmap.getAddr(x, y);
+ // now copy/convert each scanline
+ for (int y = 0; y < height; y++) {
+ proc(dst, src, width, x, y);
+ src += srcStride;
+ dst = (char*)dst + dstBitmap.rowBytes();
+ }
+
+ dstBitmap.notifyPixelsChanged();
+
+ env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
+ JNI_ABORT);
+ return true;
+}
+
+//////////////////// ToColor procs
+
+typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
+ SkColorTable*);
+
+static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ const SkPMColor* s = (const SkPMColor*)src;
+ do {
+ *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
+ } while (--width != 0);
+}
+
+static void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ const SkPMColor* s = (const SkPMColor*)src;
+ do {
+ SkPMColor c = *s++;
+ *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
+ SkGetPackedG32(c), SkGetPackedB32(c));
+ } while (--width != 0);
+}
+
+static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ const SkPMColor* s = (const SkPMColor*)src;
+ do {
+ SkPMColor c = *s++;
+ *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
+ SkGetPackedB32(c));
+ } while (--width != 0);
+}
+
+static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ const SkPMColor16* s = (const SkPMColor16*)src;
+ do {
+ *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
+ } while (--width != 0);
+}
+
+static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ const SkPMColor16* s = (const SkPMColor16*)src;
+ do {
+ SkPMColor c = SkPixel4444ToPixel32(*s++);
+ *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
+ SkGetPackedG32(c), SkGetPackedB32(c));
+ } while (--width != 0);
+}
+
+static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ const SkPMColor16* s = (const SkPMColor16*)src;
+ do {
+ SkPMColor c = SkPixel4444ToPixel32(*s++);
+ *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
+ SkGetPackedB32(c));
+ } while (--width != 0);
+}
+
+static void ToColor_S565(SkColor dst[], const void* src, int width,
+ SkColorTable*) {
+ SkASSERT(width > 0);
+ const uint16_t* s = (const uint16_t*)src;
+ do {
+ uint16_t c = *s++;
+ *dst++ = SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
+ SkPacked16ToB32(c));
+ } while (--width != 0);
+}
+
+static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
+ SkColorTable* ctable) {
+ SkASSERT(width > 0);
+ const uint8_t* s = (const uint8_t*)src;
+ const SkPMColor* colors = ctable->lockColors();
+ do {
+ *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
+ } while (--width != 0);
+ ctable->unlockColors();
+}
+
+static void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
+ SkColorTable* ctable) {
+ SkASSERT(width > 0);
+ const uint8_t* s = (const uint8_t*)src;
+ const SkPMColor* colors = ctable->lockColors();
+ do {
+ SkPMColor c = colors[*s++];
+ *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
+ SkGetPackedG32(c), SkGetPackedB32(c));
+ } while (--width != 0);
+ ctable->unlockColors();
+}
+
+static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
+ SkColorTable* ctable) {
+ SkASSERT(width > 0);
+ const uint8_t* s = (const uint8_t*)src;
+ const SkPMColor* colors = ctable->lockColors();
+ do {
+ SkPMColor c = colors[*s++];
+ *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
+ SkGetPackedB32(c));
+ } while (--width != 0);
+ ctable->unlockColors();
+}
+
+// can return NULL
+static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {
+ switch (src.config()) {
+ case SkBitmap::kARGB_8888_Config:
+ if (src.isOpaque()) return ToColor_S32_Opaque;
+ return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;
+ case SkBitmap::kARGB_4444_Config:
+ if (src.isOpaque()) return ToColor_S4444_Opaque;
+ return isPremultiplied ? ToColor_S4444_Alpha : ToColor_S4444_Raw;
+ case SkBitmap::kRGB_565_Config:
+ return ToColor_S565;
+ case SkBitmap::kIndex8_Config:
+ if (src.getColorTable() == NULL) {
+ return NULL;
+ }
+ if (src.isOpaque()) return ToColor_SI8_Opaque;
+ return isPremultiplied ? ToColor_SI8_Raw : ToColor_SI8_Alpha;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static int getPremulBitmapCreateFlags(bool isMutable) {
+ int flags = GraphicsJNI::kBitmapCreateFlag_Premultiplied;
+ if (isMutable) flags |= GraphicsJNI::kBitmapCreateFlag_Mutable;
+ return flags;
+}
+
+static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
+ jint offset, jint stride, jint width, jint height,
+ jint configHandle, jboolean isMutable) {
+ SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
+ if (NULL != jColors) {
+ size_t n = env->GetArrayLength(jColors);
+ if (n < SkAbs32(stride) * (size_t)height) {
+ doThrowAIOOBE(env);
+ return NULL;
+ }
+ }
+
+ // ARGB_4444 is a deprecated format, convert automatically to 8888
+ if (config == SkBitmap::kARGB_4444_Config) {
+ config = SkBitmap::kARGB_8888_Config;
+ }
+
+ SkBitmap bitmap;
+ bitmap.setConfig(config, width, height);
+
+ jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
+ if (NULL == buff) {
+ return NULL;
+ }
+
+ if (jColors != NULL) {
+ GraphicsJNI::SetPixels(env, jColors, offset, stride,
+ 0, 0, width, height, bitmap, true);
+ }
+
+ return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
+ getPremulBitmapCreateFlags(isMutable), NULL, NULL);
+}
+
+static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
+ jint dstConfigHandle, jboolean isMutable) {
+ const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
+ SkBitmap::Config dstConfig = static_cast<SkBitmap::Config>(dstConfigHandle);
+ SkBitmap result;
+ JavaPixelAllocator allocator(env);
+
if (!src->copyTo(&result, SkBitmapConfigToColorType(dstConfig), &allocator)) {
- return NULL;
- }
- return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),
- getPremulBitmapCreateFlags(isMutable), NULL, NULL);
-}
-
-static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
- return;
- }
-#endif // USE_OPENGL_RENDERER
- delete bitmap;
-}
-
-static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
- bool result;
- result = android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
- return result ? JNI_TRUE : JNI_FALSE;
- }
-#endif // USE_OPENGL_RENDERER
- bitmap->setPixels(NULL, NULL);
- return JNI_TRUE;
-}
-
-static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
- jint width, jint height, jint configHandle, jint allocSize) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
- if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) {
- // done in native as there's no way to get BytesPerPixel in Java
- doThrowIAE(env, "Bitmap not large enough to support new configuration");
- return;
- }
- SkPixelRef* ref = bitmap->pixelRef();
- SkSafeRef(ref);
- bitmap->setConfig(config, width, height);
- bitmap->setPixelRef(ref);
-
- // notifyPixelsChanged will increment the generation ID even though the actual pixel data
- // hasn't been touched. This signals the renderer that the bitmap (including width, height,
- // and config) has changed.
- ref->notifyPixelsChanged();
- SkSafeUnref(ref);
-}
-
-// These must match the int values in Bitmap.java
-enum JavaEncodeFormat {
- kJPEG_JavaEncodeFormat = 0,
- kPNG_JavaEncodeFormat = 1,
- kWEBP_JavaEncodeFormat = 2
-};
-
-static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
- jint format, jint quality,
- jobject jstream, jbyteArray jstorage) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkImageEncoder::Type fm;
-
- switch (format) {
- case kJPEG_JavaEncodeFormat:
- fm = SkImageEncoder::kJPEG_Type;
- break;
- case kPNG_JavaEncodeFormat:
- fm = SkImageEncoder::kPNG_Type;
- break;
- case kWEBP_JavaEncodeFormat:
- fm = SkImageEncoder::kWEBP_Type;
- break;
- default:
- return JNI_FALSE;
- }
-
- bool success = false;
- if (NULL != bitmap) {
- SkAutoLockPixels alp(*bitmap);
-
- if (NULL == bitmap->getPixels()) {
- return JNI_FALSE;
- }
-
- SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
- if (NULL == strm) {
- return JNI_FALSE;
- }
-
- SkImageEncoder* encoder = SkImageEncoder::Create(fm);
- if (NULL != encoder) {
- success = encoder->encodeStream(strm, *bitmap, quality);
- delete encoder;
- }
- delete strm;
- }
- return success ? JNI_TRUE : JNI_FALSE;
-}
-
-static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- bitmap->eraseColor(color);
-}
-
-static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return static_cast<jint>(bitmap->rowBytes());
-}
-
-static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return static_cast<jint>(bitmap->config());
-}
-
-static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return static_cast<jint>(bitmap->getGenerationID());
-}
-
-static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return !bitmap->isOpaque() ? JNI_TRUE : JNI_FALSE;
-}
-
-static void Bitmap_setAlphaAndPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
- jboolean hasAlpha, jboolean isPremul) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- if (!hasAlpha) {
- bitmap->setAlphaType(kOpaque_SkAlphaType);
- } else if (isPremul) {
- bitmap->setAlphaType(kPremul_SkAlphaType);
- } else {
- bitmap->setAlphaType(kUnpremul_SkAlphaType);
- }
-}
-
-static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
-}
-
-static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
- jboolean hasMipMap) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- bitmap->setHasHardwareMipMap(hasMipMap);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
- if (parcel == NULL) {
- SkDebugf("-------- unparcel parcel is NULL\n");
- return NULL;
- }
-
- android::Parcel* p = android::parcelForJavaObject(env, parcel);
-
- const bool isMutable = p->readInt32() != 0;
- const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
- const int width = p->readInt32();
- const int height = p->readInt32();
- const int rowBytes = p->readInt32();
- const int density = p->readInt32();
-
- if (SkBitmap::kARGB_8888_Config != config &&
- SkBitmap::kRGB_565_Config != config &&
- SkBitmap::kARGB_4444_Config != config &&
- SkBitmap::kIndex8_Config != config &&
- SkBitmap::kA8_Config != config) {
- SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
- return NULL;
- }
-
- SkBitmap* bitmap = new SkBitmap;
-
- bitmap->setConfig(config, width, height, rowBytes);
-
- SkColorTable* ctable = NULL;
- if (config == SkBitmap::kIndex8_Config) {
- int count = p->readInt32();
- if (count > 0) {
- size_t size = count * sizeof(SkPMColor);
- const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
- ctable = new SkColorTable(src, count);
- }
- }
-
- jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
- if (NULL == buffer) {
- SkSafeUnref(ctable);
- delete bitmap;
- return NULL;
- }
-
- SkSafeUnref(ctable);
-
- size_t size = bitmap->getSize();
-
- android::Parcel::ReadableBlob blob;
- android::status_t status = p->readBlob(size, &blob);
- if (status) {
- doThrowRE(env, "Could not read bitmap from parcel blob.");
- delete bitmap;
- return NULL;
- }
-
- bitmap->lockPixels();
- memcpy(bitmap->getPixels(), blob.data(), size);
- bitmap->unlockPixels();
-
- blob.release();
-
- return GraphicsJNI::createBitmap(env, bitmap, buffer, getPremulBitmapCreateFlags(isMutable),
- NULL, NULL, density);
-}
-
-static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
- jlong bitmapHandle,
- jboolean isMutable, jint density,
- jobject parcel) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- if (parcel == NULL) {
- SkDebugf("------- writeToParcel null parcel\n");
- return JNI_FALSE;
- }
-
- android::Parcel* p = android::parcelForJavaObject(env, parcel);
-
- p->writeInt32(isMutable);
- p->writeInt32(bitmap->config());
- p->writeInt32(bitmap->width());
- p->writeInt32(bitmap->height());
- p->writeInt32(bitmap->rowBytes());
- p->writeInt32(density);
-
- if (bitmap->config() == SkBitmap::kIndex8_Config) {
- SkColorTable* ctable = bitmap->getColorTable();
- if (ctable != NULL) {
- int count = ctable->count();
- p->writeInt32(count);
- memcpy(p->writeInplace(count * sizeof(SkPMColor)),
- ctable->lockColors(), count * sizeof(SkPMColor));
- ctable->unlockColors();
- } else {
- p->writeInt32(0); // indicate no ctable
- }
- }
-
- size_t size = bitmap->getSize();
-
- android::Parcel::WritableBlob blob;
- android::status_t status = p->writeBlob(size, &blob);
- if (status) {
- doThrowRE(env, "Could not write bitmap to parcel blob.");
- return JNI_FALSE;
- }
-
- bitmap->lockPixels();
- const void* pSrc = bitmap->getPixels();
- if (pSrc == NULL) {
- memset(blob.data(), 0, size);
- } else {
- memcpy(blob.data(), pSrc, size);
- }
- bitmap->unlockPixels();
-
- blob.release();
- return JNI_TRUE;
-}
-
-static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
- jlong srcHandle, jlong paintHandle,
- jintArray offsetXY) {
- const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkIPoint offset;
- SkBitmap* dst = new SkBitmap;
- JavaPixelAllocator allocator(env);
-
- src->extractAlpha(dst, paint, &allocator, &offset);
- // If Skia can't allocate pixels for destination bitmap, it resets
- // it, that is set its pixels buffer to NULL, and zero width and height.
- if (dst->getPixels() == NULL && src->getPixels() != NULL) {
- delete dst;
- doThrowOOME(env, "failed to allocate pixels for alpha");
- return NULL;
- }
- if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
- int* array = env->GetIntArrayElements(offsetXY, NULL);
- array[0] = offset.fX;
- array[1] = offset.fY;
- env->ReleaseIntArrayElements(offsetXY, array, 0);
- }
-
- return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(),
- getPremulBitmapCreateFlags(true), NULL, NULL);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
- jint x, jint y, jboolean isPremultiplied) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
-
- ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
- if (NULL == proc) {
- return 0;
- }
- const void* src = bitmap->getAddr(x, y);
- if (NULL == src) {
- return 0;
- }
-
- SkColor dst[1];
- proc(dst, src, 1, bitmap->getColorTable());
- return static_cast<jint>(dst[0]);
-}
-
-static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
- jintArray pixelArray, jint offset, jint stride,
- jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
-
- ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
- if (NULL == proc) {
- return;
- }
- const void* src = bitmap->getAddr(x, y);
- if (NULL == src) {
- return;
- }
-
- SkColorTable* ctable = bitmap->getColorTable();
- jint* dst = env->GetIntArrayElements(pixelArray, NULL);
- SkColor* d = (SkColor*)dst + offset;
- while (--height >= 0) {
- proc(d, src, width, ctable);
- d += stride;
- src = (void*)((const char*)src + bitmap->rowBytes());
- }
- env->ReleaseIntArrayElements(pixelArray, dst, 0);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
- jint x, jint y, jint colorHandle, jboolean isPremultiplied) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkColor color = static_cast<SkColor>(colorHandle);
- SkAutoLockPixels alp(*bitmap);
- if (NULL == bitmap->getPixels()) {
- return;
- }
-
- FromColorProc proc = ChooseFromColorProc(bitmap->config(), isPremultiplied);
- if (NULL == proc) {
- return;
- }
-
- proc(bitmap->getAddr(x, y), &color, 1, x, y);
- bitmap->notifyPixelsChanged();
-}
-
-static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
- jintArray pixelArray, jint offset, jint stride,
- jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
- x, y, width, height, *bitmap, isPremultiplied);
-}
-
-static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
- jlong bitmapHandle, jobject jbuffer) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
- const void* src = bitmap->getPixels();
-
- if (NULL != src) {
- android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
-
- // the java side has already checked that buffer is large enough
- memcpy(abp.pointer(), src, bitmap->getSize());
- }
-}
-
-static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
- jlong bitmapHandle, jobject jbuffer) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkAutoLockPixels alp(*bitmap);
- void* dst = bitmap->getPixels();
-
- if (NULL != dst) {
- android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
- // the java side has already checked that buffer is large enough
- memcpy(dst, abp.pointer(), bitmap->getSize());
- bitmap->notifyPixelsChanged();
- }
-}
-
-static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
- jlong bm1Handle) {
- const SkBitmap* bm0 = reinterpret_cast<SkBitmap*>(bm0Handle);
- const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle);
- if (bm0->width() != bm1->width() ||
- bm0->height() != bm1->height() ||
- bm0->config() != bm1->config()) {
- return JNI_FALSE;
- }
-
- SkAutoLockPixels alp0(*bm0);
- SkAutoLockPixels alp1(*bm1);
-
- // if we can't load the pixels, return false
- if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {
- return JNI_FALSE;
- }
-
- if (bm0->config() == SkBitmap::kIndex8_Config) {
- SkColorTable* ct0 = bm0->getColorTable();
- SkColorTable* ct1 = bm1->getColorTable();
- if (NULL == ct0 || NULL == ct1) {
- return JNI_FALSE;
- }
- if (ct0->count() != ct1->count()) {
- return JNI_FALSE;
- }
-
- SkAutoLockColors alc0(ct0);
- SkAutoLockColors alc1(ct1);
- const size_t size = ct0->count() * sizeof(SkPMColor);
- if (memcmp(alc0.colors(), alc1.colors(), size) != 0) {
- return JNI_FALSE;
- }
- }
-
- // now compare each scanline. We can't do the entire buffer at once,
- // since we don't care about the pixel values that might extend beyond
- // the width (since the scanline might be larger than the logical width)
- const int h = bm0->height();
- const size_t size = bm0->width() * bm0->bytesPerPixel();
- for (int y = 0; y < h; y++) {
- if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {
- return JNI_FALSE;
- }
- }
- return JNI_TRUE;
-}
-
-static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- bitmap->lockPixels();
- bitmap->unlockPixels();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#include <android_runtime/AndroidRuntime.h>
-
-static JNINativeMethod gBitmapMethods[] = {
- { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
- (void*)Bitmap_creator },
- { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
- (void*)Bitmap_copy },
- { "nativeDestructor", "(J)V", (void*)Bitmap_destructor },
- { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
- { "nativeReconfigure", "(JIIII)V", (void*)Bitmap_reconfigure },
- { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
- (void*)Bitmap_compress },
- { "nativeErase", "(JI)V", (void*)Bitmap_erase },
- { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
- { "nativeConfig", "(J)I", (void*)Bitmap_config },
- { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
- { "nativeSetAlphaAndPremultiplied", "(JZZ)V", (void*)Bitmap_setAlphaAndPremultiplied},
- { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
- { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
- { "nativeCreateFromParcel",
- "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
- (void*)Bitmap_createFromParcel },
- { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
- (void*)Bitmap_writeToParcel },
- { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
- (void*)Bitmap_extractAlpha },
- { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
- { "nativeGetPixel", "(JIIZ)I", (void*)Bitmap_getPixel },
- { "nativeGetPixels", "(J[IIIIIIIZ)V", (void*)Bitmap_getPixels },
- { "nativeSetPixel", "(JIIIZ)V", (void*)Bitmap_setPixel },
- { "nativeSetPixels", "(J[IIIIIIIZ)V", (void*)Bitmap_setPixels },
- { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
- (void*)Bitmap_copyPixelsToBuffer },
- { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
- (void*)Bitmap_copyPixelsFromBuffer },
- { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
- { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
-};
-
-#define kClassPathName "android/graphics/Bitmap"
-
-int register_android_graphics_Bitmap(JNIEnv* env)
-{
- return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
- gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods));
-}
+ return NULL;
+ }
+ return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),
+ getPremulBitmapCreateFlags(isMutable), NULL, NULL);
+}
+
+static void Bitmap_destructor(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+#ifdef USE_OPENGL_RENDERER
+ if (android::uirenderer::Caches::hasInstance()) {
+ android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
+ return;
+ }
+#endif // USE_OPENGL_RENDERER
+ delete bitmap;
+}
+
+static jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+#ifdef USE_OPENGL_RENDERER
+ if (android::uirenderer::Caches::hasInstance()) {
+ bool result;
+ result = android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+#endif // USE_OPENGL_RENDERER
+ bitmap->setPixels(NULL, NULL);
+ return JNI_TRUE;
+}
+
+static void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
+ jint width, jint height, jint configHandle, jint allocSize) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
+ if (width * height * SkBitmap::ComputeBytesPerPixel(config) > allocSize) {
+ // done in native as there's no way to get BytesPerPixel in Java
+ doThrowIAE(env, "Bitmap not large enough to support new configuration");
+ return;
+ }
+ SkPixelRef* ref = bitmap->pixelRef();
+ SkSafeRef(ref);
+ bitmap->setConfig(config, width, height);
+ bitmap->setPixelRef(ref);
+
+ // notifyPixelsChanged will increment the generation ID even though the actual pixel data
+ // hasn't been touched. This signals the renderer that the bitmap (including width, height,
+ // and config) has changed.
+ ref->notifyPixelsChanged();
+ SkSafeUnref(ref);
+}
+
+// These must match the int values in Bitmap.java
+enum JavaEncodeFormat {
+ kJPEG_JavaEncodeFormat = 0,
+ kPNG_JavaEncodeFormat = 1,
+ kWEBP_JavaEncodeFormat = 2
+};
+
+static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
+ jint format, jint quality,
+ jobject jstream, jbyteArray jstorage) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkImageEncoder::Type fm;
+
+ switch (format) {
+ case kJPEG_JavaEncodeFormat:
+ fm = SkImageEncoder::kJPEG_Type;
+ break;
+ case kPNG_JavaEncodeFormat:
+ fm = SkImageEncoder::kPNG_Type;
+ break;
+ case kWEBP_JavaEncodeFormat:
+ fm = SkImageEncoder::kWEBP_Type;
+ break;
+ default:
+ return JNI_FALSE;
+ }
+
+ bool success = false;
+ if (NULL != bitmap) {
+ SkAutoLockPixels alp(*bitmap);
+
+ if (NULL == bitmap->getPixels()) {
+ return JNI_FALSE;
+ }
+
+ SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
+ if (NULL == strm) {
+ return JNI_FALSE;
+ }
+
+ SkImageEncoder* encoder = SkImageEncoder::Create(fm);
+ if (NULL != encoder) {
+ success = encoder->encodeStream(strm, *bitmap, quality);
+ delete encoder;
+ }
+ delete strm;
+ }
+ return success ? JNI_TRUE : JNI_FALSE;
+}
+
+static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ bitmap->eraseColor(color);
+}
+
+static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ return static_cast<jint>(bitmap->rowBytes());
+}
+
+static jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ return static_cast<jint>(bitmap->config());
+}
+
+static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ return static_cast<jint>(bitmap->getGenerationID());
+}
+
+static jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ return !bitmap->isOpaque() ? JNI_TRUE : JNI_FALSE;
+}
+
+static void Bitmap_setAlphaAndPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
+ jboolean hasAlpha, jboolean isPremul) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ if (!hasAlpha) {
+ bitmap->setAlphaType(kOpaque_SkAlphaType);
+ } else if (isPremul) {
+ bitmap->setAlphaType(kPremul_SkAlphaType);
+ } else {
+ bitmap->setAlphaType(kUnpremul_SkAlphaType);
+ }
+}
+
+static jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
+}
+
+static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
+ jboolean hasMipMap) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ bitmap->setHasHardwareMipMap(hasMipMap);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
+ if (parcel == NULL) {
+ SkDebugf("-------- unparcel parcel is NULL\n");
+ return NULL;
+ }
+
+ android::Parcel* p = android::parcelForJavaObject(env, parcel);
+
+ const bool isMutable = p->readInt32() != 0;
+ const SkBitmap::Config config = (SkBitmap::Config)p->readInt32();
+ const int width = p->readInt32();
+ const int height = p->readInt32();
+ const int rowBytes = p->readInt32();
+ const int density = p->readInt32();
+
+ if (SkBitmap::kARGB_8888_Config != config &&
+ SkBitmap::kRGB_565_Config != config &&
+ SkBitmap::kARGB_4444_Config != config &&
+ SkBitmap::kIndex8_Config != config &&
+ SkBitmap::kA8_Config != config) {
+ SkDebugf("Bitmap_createFromParcel unknown config: %d\n", config);
+ return NULL;
+ }
+
+ SkBitmap* bitmap = new SkBitmap;
+
+ bitmap->setConfig(config, width, height, rowBytes);
+
+ SkColorTable* ctable = NULL;
+ if (config == SkBitmap::kIndex8_Config) {
+ int count = p->readInt32();
+ if (count > 0) {
+ size_t size = count * sizeof(SkPMColor);
+ const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
+ ctable = new SkColorTable(src, count);
+ }
+ }
+
+ jbyteArray buffer = GraphicsJNI::allocateJavaPixelRef(env, bitmap, ctable);
+ if (NULL == buffer) {
+ SkSafeUnref(ctable);
+ delete bitmap;
+ return NULL;
+ }
+
+ SkSafeUnref(ctable);
+
+ size_t size = bitmap->getSize();
+
+ android::Parcel::ReadableBlob blob;
+ android::status_t status = p->readBlob(size, &blob);
+ if (status) {
+ doThrowRE(env, "Could not read bitmap from parcel blob.");
+ delete bitmap;
+ return NULL;
+ }
+
+ bitmap->lockPixels();
+ memcpy(bitmap->getPixels(), blob.data(), size);
+ bitmap->unlockPixels();
+
+ blob.release();
+
+ return GraphicsJNI::createBitmap(env, bitmap, buffer, getPremulBitmapCreateFlags(isMutable),
+ NULL, NULL, density);
+}
+
+static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
+ jlong bitmapHandle,
+ jboolean isMutable, jint density,
+ jobject parcel) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ if (parcel == NULL) {
+ SkDebugf("------- writeToParcel null parcel\n");
+ return JNI_FALSE;
+ }
+
+ android::Parcel* p = android::parcelForJavaObject(env, parcel);
+
+ p->writeInt32(isMutable);
+ p->writeInt32(bitmap->config());
+ p->writeInt32(bitmap->width());
+ p->writeInt32(bitmap->height());
+ p->writeInt32(bitmap->rowBytes());
+ p->writeInt32(density);
+
+ if (bitmap->config() == SkBitmap::kIndex8_Config) {
+ SkColorTable* ctable = bitmap->getColorTable();
+ if (ctable != NULL) {
+ int count = ctable->count();
+ p->writeInt32(count);
+ memcpy(p->writeInplace(count * sizeof(SkPMColor)),
+ ctable->lockColors(), count * sizeof(SkPMColor));
+ ctable->unlockColors();
+ } else {
+ p->writeInt32(0); // indicate no ctable
+ }
+ }
+
+ size_t size = bitmap->getSize();
+
+ android::Parcel::WritableBlob blob;
+ android::status_t status = p->writeBlob(size, &blob);
+ if (status) {
+ doThrowRE(env, "Could not write bitmap to parcel blob.");
+ return JNI_FALSE;
+ }
+
+ bitmap->lockPixels();
+ const void* pSrc = bitmap->getPixels();
+ if (pSrc == NULL) {
+ memset(blob.data(), 0, size);
+ } else {
+ memcpy(blob.data(), pSrc, size);
+ }
+ bitmap->unlockPixels();
+
+ blob.release();
+ return JNI_TRUE;
+}
+
+static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
+ jlong srcHandle, jlong paintHandle,
+ jintArray offsetXY) {
+ const SkBitmap* src = reinterpret_cast<SkBitmap*>(srcHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkIPoint offset;
+ SkBitmap* dst = new SkBitmap;
+ JavaPixelAllocator allocator(env);
+
+ src->extractAlpha(dst, paint, &allocator, &offset);
+ // If Skia can't allocate pixels for destination bitmap, it resets
+ // it, that is set its pixels buffer to NULL, and zero width and height.
+ if (dst->getPixels() == NULL && src->getPixels() != NULL) {
+ delete dst;
+ doThrowOOME(env, "failed to allocate pixels for alpha");
+ return NULL;
+ }
+ if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
+ int* array = env->GetIntArrayElements(offsetXY, NULL);
+ array[0] = offset.fX;
+ array[1] = offset.fY;
+ env->ReleaseIntArrayElements(offsetXY, array, 0);
+ }
+
+ return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(),
+ getPremulBitmapCreateFlags(true), NULL, NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
+ jint x, jint y, jboolean isPremultiplied) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkAutoLockPixels alp(*bitmap);
+
+ ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
+ if (NULL == proc) {
+ return 0;
+ }
+ const void* src = bitmap->getAddr(x, y);
+ if (NULL == src) {
+ return 0;
+ }
+
+ SkColor dst[1];
+ proc(dst, src, 1, bitmap->getColorTable());
+ return static_cast<jint>(dst[0]);
+}
+
+static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
+ jintArray pixelArray, jint offset, jint stride,
+ jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkAutoLockPixels alp(*bitmap);
+
+ ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
+ if (NULL == proc) {
+ return;
+ }
+ const void* src = bitmap->getAddr(x, y);
+ if (NULL == src) {
+ return;
+ }
+
+ SkColorTable* ctable = bitmap->getColorTable();
+ jint* dst = env->GetIntArrayElements(pixelArray, NULL);
+ SkColor* d = (SkColor*)dst + offset;
+ while (--height >= 0) {
+ proc(d, src, width, ctable);
+ d += stride;
+ src = (void*)((const char*)src + bitmap->rowBytes());
+ }
+ env->ReleaseIntArrayElements(pixelArray, dst, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
+ jint x, jint y, jint colorHandle, jboolean isPremultiplied) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkColor color = static_cast<SkColor>(colorHandle);
+ SkAutoLockPixels alp(*bitmap);
+ if (NULL == bitmap->getPixels()) {
+ return;
+ }
+
+ FromColorProc proc = ChooseFromColorProc(bitmap->config(), isPremultiplied);
+ if (NULL == proc) {
+ return;
+ }
+
+ proc(bitmap->getAddr(x, y), &color, 1, x, y);
+ bitmap->notifyPixelsChanged();
+}
+
+static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
+ jintArray pixelArray, jint offset, jint stride,
+ jint x, jint y, jint width, jint height, jboolean isPremultiplied) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
+ x, y, width, height, *bitmap, isPremultiplied);
+}
+
+static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
+ jlong bitmapHandle, jobject jbuffer) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkAutoLockPixels alp(*bitmap);
+ const void* src = bitmap->getPixels();
+
+ if (NULL != src) {
+ android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
+
+ // the java side has already checked that buffer is large enough
+ memcpy(abp.pointer(), src, bitmap->getSize());
+ }
+}
+
+static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
+ jlong bitmapHandle, jobject jbuffer) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkAutoLockPixels alp(*bitmap);
+ void* dst = bitmap->getPixels();
+
+ if (NULL != dst) {
+ android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
+ // the java side has already checked that buffer is large enough
+ memcpy(dst, abp.pointer(), bitmap->getSize());
+ bitmap->notifyPixelsChanged();
+ }
+}
+
+static jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
+ jlong bm1Handle) {
+ const SkBitmap* bm0 = reinterpret_cast<SkBitmap*>(bm0Handle);
+ const SkBitmap* bm1 = reinterpret_cast<SkBitmap*>(bm1Handle);
+ if (bm0->width() != bm1->width() ||
+ bm0->height() != bm1->height() ||
+ bm0->config() != bm1->config()) {
+ return JNI_FALSE;
+ }
+
+ SkAutoLockPixels alp0(*bm0);
+ SkAutoLockPixels alp1(*bm1);
+
+ // if we can't load the pixels, return false
+ if (NULL == bm0->getPixels() || NULL == bm1->getPixels()) {
+ return JNI_FALSE;
+ }
+
+ if (bm0->config() == SkBitmap::kIndex8_Config) {
+ SkColorTable* ct0 = bm0->getColorTable();
+ SkColorTable* ct1 = bm1->getColorTable();
+ if (NULL == ct0 || NULL == ct1) {
+ return JNI_FALSE;
+ }
+ if (ct0->count() != ct1->count()) {
+ return JNI_FALSE;
+ }
+
+ SkAutoLockColors alc0(ct0);
+ SkAutoLockColors alc1(ct1);
+ const size_t size = ct0->count() * sizeof(SkPMColor);
+ if (memcmp(alc0.colors(), alc1.colors(), size) != 0) {
+ return JNI_FALSE;
+ }
+ }
+
+ // now compare each scanline. We can't do the entire buffer at once,
+ // since we don't care about the pixel values that might extend beyond
+ // the width (since the scanline might be larger than the logical width)
+ const int h = bm0->height();
+ const size_t size = bm0->width() * bm0->bytesPerPixel();
+ for (int y = 0; y < h; y++) {
+ if (memcmp(bm0->getAddr(0, y), bm1->getAddr(0, y), size) != 0) {
+ return JNI_FALSE;
+ }
+ }
+ return JNI_TRUE;
+}
+
+static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ bitmap->lockPixels();
+ bitmap->unlockPixels();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include <android_runtime/AndroidRuntime.h>
+
+static JNINativeMethod gBitmapMethods[] = {
+ { "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
+ (void*)Bitmap_creator },
+ { "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
+ (void*)Bitmap_copy },
+ { "nativeDestructor", "(J)V", (void*)Bitmap_destructor },
+ { "nativeRecycle", "(J)Z", (void*)Bitmap_recycle },
+ { "nativeReconfigure", "(JIIII)V", (void*)Bitmap_reconfigure },
+ { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z",
+ (void*)Bitmap_compress },
+ { "nativeErase", "(JI)V", (void*)Bitmap_erase },
+ { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes },
+ { "nativeConfig", "(J)I", (void*)Bitmap_config },
+ { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha },
+ { "nativeSetAlphaAndPremultiplied", "(JZZ)V", (void*)Bitmap_setAlphaAndPremultiplied},
+ { "nativeHasMipMap", "(J)Z", (void*)Bitmap_hasMipMap },
+ { "nativeSetHasMipMap", "(JZ)V", (void*)Bitmap_setHasMipMap },
+ { "nativeCreateFromParcel",
+ "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
+ (void*)Bitmap_createFromParcel },
+ { "nativeWriteToParcel", "(JZILandroid/os/Parcel;)Z",
+ (void*)Bitmap_writeToParcel },
+ { "nativeExtractAlpha", "(JJ[I)Landroid/graphics/Bitmap;",
+ (void*)Bitmap_extractAlpha },
+ { "nativeGenerationId", "(J)I", (void*)Bitmap_getGenerationId },
+ { "nativeGetPixel", "(JIIZ)I", (void*)Bitmap_getPixel },
+ { "nativeGetPixels", "(J[IIIIIIIZ)V", (void*)Bitmap_getPixels },
+ { "nativeSetPixel", "(JIIIZ)V", (void*)Bitmap_setPixel },
+ { "nativeSetPixels", "(J[IIIIIIIZ)V", (void*)Bitmap_setPixels },
+ { "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
+ (void*)Bitmap_copyPixelsToBuffer },
+ { "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
+ (void*)Bitmap_copyPixelsFromBuffer },
+ { "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
+ { "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
+};
+
+#define kClassPathName "android/graphics/Bitmap"
+
+int register_android_graphics_Bitmap(JNIEnv* env)
+{
+ return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
+ gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods));
+}