diff options
| -rw-r--r-- | api/test-current.txt | 4 | ||||
| -rwxr-xr-x | core/jni/android/graphics/Bitmap.cpp | 26 | ||||
| -rw-r--r-- | core/jni/android/graphics/Graphics.cpp | 2 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Bitmap.java | 28 |
4 files changed, 59 insertions, 1 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 957f957d21a3..928aa08591e1 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -494,6 +494,10 @@ package android.database.sqlite { package android.graphics { + public final class Bitmap implements android.os.Parcelable { + method public void eraseColor(long); + } + public final class ImageDecoder implements java.lang.AutoCloseable { method public static android.graphics.ImageDecoder.Source createSource(android.content.res.Resources, java.io.InputStream, int); } diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index eb7338a7ce58..f188a0fcd87d 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -568,11 +568,34 @@ static jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle, return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE; } +static inline void bitmapErase(SkBitmap bitmap, const SkColor4f& color, + const sk_sp<SkColorSpace>& colorSpace) { + SkPaint p; + p.setColor4f(color, colorSpace.get()); + p.setBlendMode(SkBlendMode::kSrc); + SkCanvas canvas(bitmap); + canvas.drawPaint(p); +} + static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) { LocalScopedBitmap bitmap(bitmapHandle); SkBitmap skBitmap; bitmap->getSkBitmap(&skBitmap); - skBitmap.eraseColor(color); + bitmapErase(skBitmap, SkColor4f::FromColor(color), SkColorSpace::MakeSRGB()); +} + +static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle, jobject jColorSpace, + jfloat r, jfloat g, jfloat b, jfloat a) { + sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(env, jColorSpace); + if (GraphicsJNI::hasException(env)) { + return; + } + + LocalScopedBitmap bitmap(bitmapHandle); + SkBitmap skBitmap; + bitmap->getSkBitmap(&skBitmap); + SkColor4f color = SkColor4f{r, g, b, a}; + bitmapErase(skBitmap, color, cs); } static jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) { @@ -1183,6 +1206,7 @@ static const JNINativeMethod gBitmapMethods[] = { { "nativeCompress", "(JIILjava/io/OutputStream;[B)Z", (void*)Bitmap_compress }, { "nativeErase", "(JI)V", (void*)Bitmap_erase }, + { "nativeErase", "(JLandroid/graphics/ColorSpace;FFFF)V", (void*)Bitmap_eraseLong }, { "nativeRowBytes", "(J)I", (void*)Bitmap_rowBytes }, { "nativeConfig", "(J)I", (void*)Bitmap_config }, { "nativeHasAlpha", "(J)Z", (void*)Bitmap_hasAlpha }, diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 67d0c8aced61..548a249d9472 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -456,12 +456,14 @@ sk_sp<SkColorSpace> GraphicsJNI::getNativeColorSpace(JNIEnv* env, jobject colorS if (colorSpace == nullptr) return nullptr; if (!env->IsInstanceOf(colorSpace, gColorSpaceRGB_class)) { doThrowIAE(env, "The color space must be an RGB color space"); + return nullptr; } jobject transferParams = env->CallObjectMethod(colorSpace, gColorSpaceRGB_getTransferParametersMethodID); if (transferParams == nullptr) { doThrowIAE(env, "The color space must use an ICC parametric transfer function"); + return nullptr; } jfloatArray illuminantD50 = (jfloatArray) env->GetStaticObjectField(gColorSpace_class, diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 790b37eec4c5..30f0bfa68b4a 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -18,9 +18,11 @@ package android.graphics; import android.annotation.CheckResult; import android.annotation.ColorInt; +import android.annotation.ColorLong; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.annotation.WorkerThread; import android.content.res.ResourcesImpl; @@ -1780,6 +1782,30 @@ public final class Bitmap implements Parcelable { } /** + * Fills the bitmap's pixels with the specified {@link Color}. + * + * @throws IllegalStateException if the bitmap is not mutable. + * @throws IllegalArgumentException if the color space encoded in the long + * is invalid or unknown. + * + * @hide pending API approval + */ + @TestApi + public void eraseColor(@ColorLong long c) { + checkRecycled("Can't erase a recycled bitmap"); + if (!isMutable()) { + throw new IllegalStateException("cannot erase immutable bitmaps"); + } + + ColorSpace cs = Color.colorSpace(c); + float r = Color.red(c); + float g = Color.green(c); + float b = Color.blue(c); + float a = Color.alpha(c); + nativeErase(mNativePtr, cs, r, g, b, a); + } + + /** * Returns the {@link Color} at the specified location. Throws an exception * if x or y are out of bounds (negative or >= to the width or height * respectively). The returned color is a non-premultiplied ARGB value in @@ -2123,6 +2149,8 @@ public final class Bitmap implements Parcelable { int quality, OutputStream stream, byte[] tempStorage); private static native void nativeErase(long nativeBitmap, int color); + private static native void nativeErase(long nativeBitmap, ColorSpace cs, + float r, float g, float b, float a); private static native int nativeRowBytes(long nativeBitmap); private static native int nativeConfig(long nativeBitmap); |