Loading api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -8831,6 +8831,7 @@ package android.graphics { method public void setHeight(int); method public void setPixel(int, int, int); method public void setPixels(int[], int, int, int, int, int, int); method public final void setPremultiplied(boolean); method public void setWidth(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; Loading Loading @@ -8880,6 +8881,7 @@ package android.graphics { field public boolean inMutable; field public boolean inPreferQualityOverSpeed; field public android.graphics.Bitmap.Config inPreferredConfig; field public boolean inPremultiplied; field public boolean inPurgeable; field public int inSampleSize; field public boolean inScaled; core/java/android/view/GLES20Canvas.java +7 −7 Original line number Diff line number Diff line Loading @@ -776,7 +776,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawPatch(NinePatch patch, Rect dst, Paint paint) { Bitmap bitmap = patch.getBitmap(); if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing patches int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; try { Loading @@ -791,7 +791,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawPatch(NinePatch patch, RectF dst, Paint paint) { Bitmap bitmap = patch.getBitmap(); if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing patches int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; try { Loading @@ -808,7 +808,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading @@ -824,7 +824,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading @@ -841,7 +841,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading @@ -868,7 +868,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading Loading @@ -944,7 +944,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) { throw new ArrayIndexOutOfBoundsException(); } Loading core/jni/android/graphics/Bitmap.cpp +116 −45 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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: Loading @@ -77,13 +110,12 @@ static FromColorProc ChooseFromColorProc(SkBitmap::Config config) { return NULL; } bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride, bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride, int x, int y, int width, int height, const SkBitmap& dstBitmap) { 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; Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; } Loading @@ -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) { Loading @@ -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, Loading @@ -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) { Loading Loading @@ -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(); } Loading Loading @@ -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, Loading Loading @@ -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; } Loading @@ -552,10 +625,10 @@ 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) { 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; } Loading @@ -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; } Loading @@ -595,9 +668,9 @@ 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) { 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, Loading Loading @@ -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 }, Loading @@ -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", Loading core/jni/android/graphics/BitmapFactory.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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; Loading Loading @@ -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; Loading @@ -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)) { Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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"); Loading core/jni/android/graphics/BitmapFactory.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -8831,6 +8831,7 @@ package android.graphics { method public void setHeight(int); method public void setPixel(int, int, int); method public void setPixels(int[], int, int, int, int, int, int); method public final void setPremultiplied(boolean); method public void setWidth(int); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; Loading Loading @@ -8880,6 +8881,7 @@ package android.graphics { field public boolean inMutable; field public boolean inPreferQualityOverSpeed; field public android.graphics.Bitmap.Config inPreferredConfig; field public boolean inPremultiplied; field public boolean inPurgeable; field public int inSampleSize; field public boolean inScaled;
core/java/android/view/GLES20Canvas.java +7 −7 Original line number Diff line number Diff line Loading @@ -776,7 +776,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawPatch(NinePatch patch, Rect dst, Paint paint) { Bitmap bitmap = patch.getBitmap(); if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing patches int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; try { Loading @@ -791,7 +791,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawPatch(NinePatch patch, RectF dst, Paint paint) { Bitmap bitmap = patch.getBitmap(); if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing patches int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE; try { Loading @@ -808,7 +808,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading @@ -824,7 +824,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading @@ -841,7 +841,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading @@ -868,7 +868,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); // Shaders are ignored when drawing bitmaps int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE; try { Loading Loading @@ -944,7 +944,7 @@ class GLES20Canvas extends HardwareCanvas { @Override public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, Paint paint) { if (bitmap.isRecycled()) throw new IllegalArgumentException("Cannot draw recycled bitmaps"); throwIfCannotDraw(bitmap); if (meshWidth < 0 || meshHeight < 0 || vertOffset < 0 || colorOffset < 0) { throw new ArrayIndexOutOfBoundsException(); } Loading
core/jni/android/graphics/Bitmap.cpp +116 −45 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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: Loading @@ -77,13 +110,12 @@ static FromColorProc ChooseFromColorProc(SkBitmap::Config config) { return NULL; } bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride, bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride, int x, int y, int width, int height, const SkBitmap& dstBitmap) { 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; Loading Loading @@ -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); Loading @@ -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); Loading Loading @@ -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); Loading @@ -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; } Loading @@ -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) { Loading @@ -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, Loading @@ -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) { Loading Loading @@ -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(); } Loading Loading @@ -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, Loading Loading @@ -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; } Loading @@ -552,10 +625,10 @@ 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) { 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; } Loading @@ -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; } Loading @@ -595,9 +668,9 @@ 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) { 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, Loading Loading @@ -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 }, Loading @@ -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", Loading
core/jni/android/graphics/BitmapFactory.cpp +14 −2 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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; Loading Loading @@ -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; Loading @@ -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)) { Loading @@ -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; Loading Loading @@ -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, Loading Loading @@ -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"); Loading
core/jni/android/graphics/BitmapFactory.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading