diff options
Diffstat (limited to 'core/jni')
| -rw-r--r-- | core/jni/android/graphics/Bitmap.cpp | 161 | ||||
| -rw-r--r-- | core/jni/android/graphics/BitmapFactory.cpp | 16 | ||||
| -rw-r--r-- | core/jni/android/graphics/BitmapFactory.h | 1 | ||||
| -rw-r--r-- | core/jni/android/graphics/BitmapRegionDecoder.cpp | 10 | ||||
| -rw-r--r-- | core/jni/android/graphics/Canvas.cpp | 7 | ||||
| -rw-r--r-- | core/jni/android/graphics/Graphics.cpp | 28 | ||||
| -rw-r--r-- | core/jni/android/graphics/GraphicsJNI.h | 22 | ||||
| -rw-r--r-- | core/jni/android_emoji_EmojiFactory.cpp | 16 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 2 | ||||
| -rw-r--r-- | core/jni/android_view_SurfaceControl.cpp | 3 |
10 files changed, 178 insertions, 88 deletions
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 0ea3bf7..fd9fbae 100644 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -38,6 +38,23 @@ static void FromColor_D32(void* dst, const SkColor src[], int width, }
}
+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;
@@ -56,19 +73,35 @@ static void FromColor_D4444(void* dst, const SkColor src[], int width, DITHER_4444_SCAN(y);
for (int stop = x + width; x < stop; x++) {
- SkPMColor c = SkPreMultiplyColor(*src++);
- *d++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
-// *d++ = SkPixel32ToPixel4444(c);
+ 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) {
+static FromColorProc ChooseFromColorProc(SkBitmap::Config config, bool isPremultiplied) {
switch (config) {
case SkBitmap::kARGB_8888_Config:
- return FromColor_D32;
+ return isPremultiplied ? FromColor_D32 : FromColor_D32_Raw;
case SkBitmap::kARGB_4444_Config:
- return FromColor_D4444;
+ return isPremultiplied ? FromColor_D4444 : FromColor_D4444_Raw;
case SkBitmap::kRGB_565_Config:
return FromColor_D565;
default:
@@ -77,13 +110,12 @@ static FromColorProc ChooseFromColorProc(SkBitmap::Config config) { 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 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());
+ FromColorProc proc = ChooseFromColorProc(dstBitmap.config(), isPremultiplied);
if (NULL == dst || NULL == proc) {
return false;
@@ -122,6 +154,17 @@ static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width, } 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);
@@ -142,6 +185,17 @@ static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width, } 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);
@@ -175,6 +229,19 @@ static void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width, ctable->unlockColors(false);
}
+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(false);
+}
+
static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
SkColorTable* ctable) {
SkASSERT(width > 0);
@@ -189,19 +256,22 @@ static void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width, }
// can return NULL
-static ToColorProc ChooseToColorProc(const SkBitmap& src) {
+static ToColorProc ChooseToColorProc(const SkBitmap& src, bool isPremultiplied) {
switch (src.config()) {
case SkBitmap::kARGB_8888_Config:
- return src.isOpaque() ? ToColor_S32_Opaque : ToColor_S32_Alpha;
+ if (src.isOpaque()) return ToColor_S32_Opaque;
+ return isPremultiplied ? ToColor_S32_Alpha : ToColor_S32_Raw;
case SkBitmap::kARGB_4444_Config:
- return src.isOpaque() ? ToColor_S4444_Opaque : ToColor_S4444_Alpha;
+ 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;
}
- return src.isOpaque() ? ToColor_SI8_Opaque : ToColor_SI8_Alpha;
+ if (src.isOpaque()) return ToColor_SI8_Opaque;
+ return isPremultiplied ? ToColor_SI8_Raw : ToColor_SI8_Alpha;
default:
break;
}
@@ -211,6 +281,12 @@ static ToColorProc ChooseToColorProc(const SkBitmap& src) { ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
+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,
int offset, int stride, int width, int height,
SkBitmap::Config config, jboolean isMutable) {
@@ -236,10 +312,12 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, }
if (jColors != NULL) {
- GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
+ GraphicsJNI::SetPixels(env, jColors, offset, stride,
+ 0, 0, width, height, bitmap, true);
}
- return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);
+ return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
+ getPremulBitmapCreateFlags(isMutable), NULL, NULL);
}
static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
@@ -250,8 +328,8 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src, if (!src->copyTo(&result, dstConfig, &allocator)) {
return NULL;
}
-
- return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL, NULL);
+ return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(),
+ getPremulBitmapCreateFlags(isMutable), NULL, NULL);
}
static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
@@ -347,14 +425,6 @@ static void Bitmap_erase(JNIEnv* env, jobject, SkBitmap* bitmap, jint color) { bitmap->eraseColor(color);
}
-static int Bitmap_width(JNIEnv* env, jobject, SkBitmap* bitmap) {
- return bitmap->width();
-}
-
-static int Bitmap_height(JNIEnv* env, jobject, SkBitmap* bitmap) {
- return bitmap->height();
-}
-
static int Bitmap_rowBytes(JNIEnv* env, jobject, SkBitmap* bitmap) {
return bitmap->rowBytes();
}
@@ -449,7 +519,9 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { bitmap->unlockPixels();
blob.release();
- return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, NULL, density);
+
+ return GraphicsJNI::createBitmap(env, bitmap, buffer, getPremulBitmapCreateFlags(isMutable),
+ NULL, NULL, density);
}
static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
@@ -527,16 +599,17 @@ static jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz, env->ReleaseIntArrayElements(offsetXY, array, 0);
}
- return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL, NULL);
+ return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(),
+ GraphicsJNI::kBitmapCreateFlag_Mutable, NULL, NULL);
}
///////////////////////////////////////////////////////////////////////////////
static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
- int x, int y) {
+ int x, int y, bool isPremultiplied) {
SkAutoLockPixels alp(*bitmap);
- ToColorProc proc = ChooseToColorProc(*bitmap);
+ ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
if (NULL == proc) {
return 0;
}
@@ -551,11 +624,11 @@ static int Bitmap_getPixel(JNIEnv* env, jobject, const SkBitmap* bitmap, }
static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
- jintArray pixelArray, int offset, int stride,
- int x, int y, int width, int height) {
+ jintArray pixelArray, int offset, int stride,
+ int x, int y, int width, int height, bool isPremultiplied) {
SkAutoLockPixels alp(*bitmap);
- ToColorProc proc = ChooseToColorProc(*bitmap);
+ ToColorProc proc = ChooseToColorProc(*bitmap, isPremultiplied);
if (NULL == proc) {
return;
}
@@ -578,13 +651,13 @@ static void Bitmap_getPixels(JNIEnv* env, jobject, const SkBitmap* bitmap, ///////////////////////////////////////////////////////////////////////////////
static void Bitmap_setPixel(JNIEnv* env, jobject, const SkBitmap* bitmap,
- int x, int y, SkColor color) {
+ int x, int y, SkColor color, bool isPremultiplied) {
SkAutoLockPixels alp(*bitmap);
if (NULL == bitmap->getPixels()) {
return;
}
- FromColorProc proc = ChooseFromColorProc(bitmap->config());
+ FromColorProc proc = ChooseFromColorProc(bitmap->config(), isPremultiplied);
if (NULL == proc) {
return;
}
@@ -594,10 +667,10 @@ static void Bitmap_setPixel(JNIEnv* env, jobject, const SkBitmap* bitmap, }
static void Bitmap_setPixels(JNIEnv* env, jobject, const SkBitmap* bitmap,
- jintArray pixelArray, int offset, int stride,
- int x, int y, int width, int height) {
+ jintArray pixelArray, int offset, int stride,
+ int x, int y, int width, int height, bool isPremultiplied) {
GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
- x, y, width, height, *bitmap);
+ x, y, width, height, *bitmap, isPremultiplied);
}
static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
@@ -693,8 +766,6 @@ static JNINativeMethod gBitmapMethods[] = { { "nativeCompress", "(IIILjava/io/OutputStream;[B)Z",
(void*)Bitmap_compress },
{ "nativeErase", "(II)V", (void*)Bitmap_erase },
- { "nativeWidth", "(I)I", (void*)Bitmap_width },
- { "nativeHeight", "(I)I", (void*)Bitmap_height },
{ "nativeRowBytes", "(I)I", (void*)Bitmap_rowBytes },
{ "nativeConfig", "(I)I", (void*)Bitmap_config },
{ "nativeHasAlpha", "(I)Z", (void*)Bitmap_hasAlpha },
@@ -709,10 +780,10 @@ static JNINativeMethod gBitmapMethods[] = { { "nativeExtractAlpha", "(II[I)Landroid/graphics/Bitmap;",
(void*)Bitmap_extractAlpha },
{ "nativeGenerationId", "(I)I", (void*)Bitmap_getGenerationId },
- { "nativeGetPixel", "(III)I", (void*)Bitmap_getPixel },
- { "nativeGetPixels", "(I[IIIIIII)V", (void*)Bitmap_getPixels },
- { "nativeSetPixel", "(IIII)V", (void*)Bitmap_setPixel },
- { "nativeSetPixels", "(I[IIIIIII)V", (void*)Bitmap_setPixels },
+ { "nativeGetPixel", "(IIIZ)I", (void*)Bitmap_getPixel },
+ { "nativeGetPixels", "(I[IIIIIIIZ)V", (void*)Bitmap_getPixels },
+ { "nativeSetPixel", "(IIIIZ)V", (void*)Bitmap_setPixel },
+ { "nativeSetPixels", "(I[IIIIIIIZ)V", (void*)Bitmap_setPixels },
{ "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",
(void*)Bitmap_copyPixelsToBuffer },
{ "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 49e3aa4..c433874 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -14,6 +14,7 @@ #include "AutoDecodeCancel.h" #include "Utils.h" #include "JNIHelp.h" +#include "GraphicsJNI.h" #include <android_runtime/AndroidRuntime.h> #include <androidfw/Asset.h> @@ -25,6 +26,7 @@ jfieldID gOptions_justBoundsFieldID; jfieldID gOptions_sampleSizeFieldID; jfieldID gOptions_configFieldID; +jfieldID gOptions_premultipliedFieldID; jfieldID gOptions_mutableFieldID; jfieldID gOptions_ditherFieldID; jfieldID gOptions_purgeableFieldID; @@ -213,6 +215,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, float scale = 1.0f; bool isPurgeable = forcePurgeable || (allowPurgeable && optionsPurgeable(env, options)); bool preferQualityOverSpeed = false; + bool requireUnpremultiplied = false; jobject javaBitmap = NULL; @@ -233,6 +236,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, doDither = env->GetBooleanField(options, gOptions_ditherFieldID); preferQualityOverSpeed = env->GetBooleanField(options, gOptions_preferQualityOverSpeedFieldID); + requireUnpremultiplied = !env->GetBooleanField(options, gOptions_premultipliedFieldID); javaBitmap = env->GetObjectField(options, gOptions_bitmapFieldID); if (env->GetBooleanField(options, gOptions_scaledFieldID)) { @@ -256,6 +260,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, decoder->setSampleSize(sampleSize); decoder->setDitherImage(doDither); decoder->setPreferQualityOverSpeed(preferQualityOverSpeed); + decoder->setRequireUnpremultipliedColors(requireUnpremultiplied); SkBitmap* outputBitmap = NULL; unsigned int existingBufferSize = 0; @@ -434,14 +439,20 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, adb.detach(); if (javaBitmap != NULL) { - GraphicsJNI::reinitBitmap(env, javaBitmap); + bool isPremultiplied = !requireUnpremultiplied; + GraphicsJNI::reinitBitmap(env, javaBitmap, outputBitmap, isPremultiplied); outputBitmap->notifyPixelsChanged(); // If a java bitmap was passed in for reuse, pass it back return javaBitmap; } + + int bitmapCreateFlags = 0x0; + if (isMutable) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Mutable; + if (!requireUnpremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied; + // now create the java bitmap return GraphicsJNI::createBitmap(env, outputBitmap, javaAllocator.getStorageObj(), - isMutable, ninePatchChunk, layoutBounds, -1); + bitmapCreateFlags, ninePatchChunk, layoutBounds, -1); } static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage, @@ -624,6 +635,7 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { gOptions_sampleSizeFieldID = getFieldIDCheck(env, options_class, "inSampleSize", "I"); gOptions_configFieldID = getFieldIDCheck(env, options_class, "inPreferredConfig", "Landroid/graphics/Bitmap$Config;"); + gOptions_premultipliedFieldID = getFieldIDCheck(env, options_class, "inPremultiplied", "Z"); gOptions_mutableFieldID = getFieldIDCheck(env, options_class, "inMutable", "Z"); gOptions_ditherFieldID = getFieldIDCheck(env, options_class, "inDither", "Z"); gOptions_purgeableFieldID = getFieldIDCheck(env, options_class, "inPurgeable", "Z"); diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h index f2aaab7..97dcc6d 100644 --- a/core/jni/android/graphics/BitmapFactory.h +++ b/core/jni/android/graphics/BitmapFactory.h @@ -7,6 +7,7 @@ extern jclass gOptions_class; extern jfieldID gOptions_justBoundsFieldID; extern jfieldID gOptions_sampleSizeFieldID; extern jfieldID gOptions_configFieldID; +extern jfieldID gOptions_premultipliedFieldID; extern jfieldID gOptions_ditherFieldID; extern jfieldID gOptions_purgeableFieldID; extern jfieldID gOptions_shareableFieldID; diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp index 10ef60a..0c0ebbb 100644 --- a/core/jni/android/graphics/BitmapRegionDecoder.cpp +++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp @@ -201,6 +201,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *b SkBitmap::Config prefConfig = SkBitmap::kNo_Config; bool doDither = true; bool preferQualityOverSpeed = false; + bool requireUnpremultiplied = false; if (NULL != options) { sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); @@ -216,11 +217,13 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *b gOptions_preferQualityOverSpeedFieldID); // Get the bitmap for re-use if it exists. tileBitmap = env->GetObjectField(options, gOptions_bitmapFieldID); + requireUnpremultiplied = env->GetBooleanField(options, gOptions_premultipliedFieldID); } decoder->setDitherImage(doDither); decoder->setPreferQualityOverSpeed(preferQualityOverSpeed); - AutoDecoderCancel adc(options, decoder); + decoder->setRequireUnpremultipliedColors(requireUnpremultiplied); + AutoDecoderCancel adc(options, decoder); // To fix the race condition in case "requestCancelDecode" // happens earlier than AutoDecoderCancel object is added @@ -270,7 +273,10 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, SkBitmapRegionDecoder *b JavaPixelAllocator* allocator = (JavaPixelAllocator*) decoder->getAllocator(); jbyteArray buff = allocator->getStorageObjAndReset(); - return GraphicsJNI::createBitmap(env, bitmap, buff, false, NULL, NULL, -1); + + int bitmapCreateFlags = 0; + if (!requireUnpremultiplied) bitmapCreateFlags |= GraphicsJNI::kBitmapCreateFlag_Premultiplied; + return GraphicsJNI::createBitmap(env, bitmap, buff, bitmapCreateFlags, NULL, NULL, -1); } static int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) { diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp index 6c4526e..813dd5a 100644 --- a/core/jni/android/graphics/Canvas.cpp +++ b/core/jni/android/graphics/Canvas.cpp @@ -547,18 +547,17 @@ public: jboolean hasAlpha, SkPaint* paint) { SkBitmap bitmap; - bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config : SkBitmap::kRGB_565_Config, width, height); if (!bitmap.allocPixels()) { return; } - + if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, - 0, 0, width, height, bitmap)) { + 0, 0, width, height, bitmap, true)) { return; } - + canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y), paint); } diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 7c420ad..ef5b7c9 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -347,27 +347,32 @@ SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region) /////////////////////////////////////////////////////////////////////////////////////////// jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer, - bool isMutable, jbyteArray ninepatch, jintArray layoutbounds, - int density) + int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density) { SkASSERT(bitmap); SkASSERT(bitmap->pixelRef()); + bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable; + bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied; + jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID, - static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), - buffer, isMutable, ninepatch, layoutbounds, density); + static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), buffer, + bitmap->width(), bitmap->height(), density, isMutable, isPremultiplied, + ninepatch, layoutbounds); hasException(env); // For the side effect of logging. return obj; } -jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, - jbyteArray ninepatch, int density) +jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags, + jbyteArray ninepatch, int density) { - return createBitmap(env, bitmap, NULL, isMutable, ninepatch, NULL, density); + return createBitmap(env, bitmap, NULL, bitmapCreateFlags, ninepatch, NULL, density); } -void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap) +void GraphicsJNI::reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap, + bool isPremultiplied) { - env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID); + env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID, + bitmap->width(), bitmap->height(), isPremultiplied); } int GraphicsJNI::getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap) @@ -593,9 +598,8 @@ int register_android_graphics_Graphics(JNIEnv* env) gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I"); - gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", - "(I[BZ[B[II)V"); - gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "()V"); + gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(I[BIIIZZ[B[I)V"); + gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V"); gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I"); gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder"); gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V"); diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index b676527..5a2a6f8 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -17,6 +17,12 @@ class SkPicture; class GraphicsJNI { public: + enum BitmapCreateFlags { + kBitmapCreateFlag_None = 0x0, + kBitmapCreateFlag_Mutable = 0x1, + kBitmapCreateFlag_Premultiplied = 0x2, + }; + // returns true if an exception is set (and dumps it out to the Log) static bool hasException(JNIEnv*); @@ -53,13 +59,13 @@ public: storage array (may be null). */ static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer, - bool isMutable, jbyteArray ninepatch, jintArray layoutbounds, - int density = -1); + int bitmapCreateFlags, jbyteArray ninepatch, jintArray layoutbounds, int density = -1); - static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable, - jbyteArray ninepatch, int density = -1); + static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, int bitmapCreateFlags, + jbyteArray ninepatch, int density = -1); - static void reinitBitmap(JNIEnv* env, jobject javaBitmap); + static void reinitBitmap(JNIEnv* env, jobject javaBitmap, SkBitmap* bitmap, + bool isPremultiplied); static int getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap); @@ -68,14 +74,14 @@ public: static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap); static jbyteArray allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, - SkColorTable* ctable); + SkColorTable* ctable); /** Copy the colors in colors[] to the bitmap, convert to the correct format along the way. */ static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset, - int srcStride, int x, int y, int width, int height, - const SkBitmap& dstBitmap); + int srcStride, int x, int y, int width, int height, + const SkBitmap& dstBitmap, bool isPremultiplied); static jbyteArray getBitmapStorageObj(SkPixelRef *pixref); }; diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp index 4383997..5276934 100644 --- a/core/jni/android_emoji_EmojiFactory.cpp +++ b/core/jni/android_emoji_EmojiFactory.cpp @@ -6,6 +6,7 @@ #include <ScopedUtfChars.h> #include "EmojiFactory.h" +#include "GraphicsJNI.h" #include <nativehelper/JNIHelp.h> #include <dlfcn.h> @@ -92,9 +93,6 @@ static EmojiFactoryCaller* gCaller; static pthread_once_t g_once = PTHREAD_ONCE_INIT; static bool lib_emoji_factory_is_ready; -static jclass gBitmap_class; -static jmethodID gBitmap_constructorMethodID; - static jclass gEmojiFactory_class; static jmethodID gEmojiFactory_constructorMethodID; @@ -172,13 +170,8 @@ static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua( return NULL; } - jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID, - static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), NULL, false, NULL, -1); - if (env->ExceptionCheck() != 0) { - ALOGE("*** Uncaught exception returned from Java call!\n"); - env->ExceptionDescribe(); - } - return obj; + return GraphicsJNI::createBitmap(env, bitmap, + GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL); } static void android_emoji_EmojiFactory_destructor( @@ -281,9 +274,6 @@ static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, } int register_android_emoji_EmojiFactory(JNIEnv* env) { - gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); - gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", - "(I[BZ[BI)V"); gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory"); gEmojiFactory_constructorMethodID = env->GetMethodID( gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V"); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 6d46cf9..dc90da7 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -417,7 +417,7 @@ static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz, return; } - if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap)) { + if (!GraphicsJNI::SetPixels(env, colors, offset, stride, 0, 0, width, height, *bitmap, true)) { delete bitmap; return; } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 19f56cd..67eade8 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -195,7 +195,8 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, jobject display bitmap->setPixels(NULL); } - return GraphicsJNI::createBitmap(env, bitmap, false, NULL); + return GraphicsJNI::createBitmap(env, bitmap, + GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL); } static void nativeScreenshot(JNIEnv* env, jclass clazz, |
