Implement Bitmap get/setPixel(s) using SkBitmap::read/writePixels

Test: Ran CtsUiRenderingTestCases and android.graphics.cts
Change-Id: Ib32fb41d763a29919ac4744c876eb7af42fabab2
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 02076bd..8083a6a 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -310,180 +310,17 @@
 using namespace android;
 using namespace android::bitmap;
 
-///////////////////////////////////////////////////////////////////////////////
-// 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_F16(void* dst, const SkColor src[], int width,
-                          int, int) {
-    uint64_t* d = (uint64_t*)dst;
-
-    for (int i = 0; i < width; i++) {
-        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
-    }
-}
-
-static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
-                          int, int) {
-    uint64_t* d = (uint64_t*)dst;
-
-    for (int i = 0; i < width; i++) {
-        const SkColor4f color = SkColor4f::FromColor(*src++);
-        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
-        scratch[0] = SkFloatToHalf(color.fR);
-        scratch[1] = SkFloatToHalf(color.fG);
-        scratch[2] = SkFloatToHalf(color.fB);
-        scratch[3] = SkFloatToHalf(color.fA);
-    }
-}
-
-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) {
-    // Needed to thwart the unreachable code detection from clang.
-    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
-
-    // SkColor's ordering may be different from SkPMColor
-    if (sk_color_ne_zero) {
-        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);
-    }
-}
-
-static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
-    uint8_t* d = (uint8_t*)dst;
-
-    for (int stop = x + width; x < stop; x++) {
-        *d++ = SkColorGetA(*src++);
-    }
-}
-
-// can return NULL
-static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
-    switch (bitmap.colorType()) {
-        case kN32_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
-        case kARGB_4444_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
-                    FromColor_D4444_Raw;
-        case kRGB_565_SkColorType:
-            return FromColor_D565;
-        case kAlpha_8_SkColorType:
-            return FromColor_DA8;
-        case kRGBA_F16_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
-        default:
-            break;
-    }
-    return NULL;
-}
-
-static bool IsColorSpaceSRGB(SkColorSpace* colorSpace) {
-    return colorSpace == nullptr || colorSpace->isSRGB();
-}
-
 bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
-        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
-    void* dst = dstBitmap.getPixels();
-    FromColorProc proc = ChooseFromColorProc(dstBitmap);
-
-    if (NULL == dst || NULL == proc) {
-        return false;
-    }
-
+        int x, int y, int width, int height, SkBitmap* dstBitmap) {
     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);
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo srcInfo = SkImageInfo::Make(
+            width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
+    SkPixmap srcPM(srcInfo, src, srcStride * 4);
 
-    SkColorSpace* colorSpace = dstBitmap.colorSpace();
-    if (dstBitmap.colorType() == kRGBA_F16_SkColorType || IsColorSpaceSRGB(colorSpace)) {
-        // 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();
-        }
-    } else {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
-
-        std::unique_ptr<SkColor[]> row(new SkColor[width]);
-
-        // now copy/convert each scanline
-        for (int y = 0; y < height; y++) {
-            memcpy(row.get(), src, sizeof(SkColor) * width);
-            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
-                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
-                    SkAlphaType::kUnpremul_SkAlphaType);
-
-            proc(dst, row.get(), width, x, y);
-            src += srcStride;
-            dst = (char*)dst + dstBitmap.rowBytes();
-        }
-    }
-
-    dstBitmap.notifyPixelsChanged();
+    dstBitmap->writePixels(srcPM, x, y);
 
     env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
     return true;
@@ -491,90 +328,6 @@
 
 //////////////////// ToColor procs
 
-typedef void (*ToColorProc)(SkColor dst[], const void* src, int width);
-
-static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    uint64_t* s = (uint64_t*)src;
-    do {
-        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
-    } while (--width != 0);
-}
-
-static void ToColor_F16_Raw(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    uint64_t* s = (uint64_t*)src;
-    do {
-        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
-    } while (--width != 0);
-}
-
-static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width) {
-    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) {
-    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) {
-    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) {
-    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) {
-    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) {
-    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) {
-    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_SA8(SkColor dst[], const void* src, int width) {
     SkASSERT(width > 0);
     const uint8_t* s = (const uint8_t*)src;
@@ -584,52 +337,6 @@
     } while (--width != 0);
 }
 
-// can return NULL
-static ToColorProc ChooseToColorProc(const SkBitmap& src) {
-    switch (src.colorType()) {
-        case kN32_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_S32_Opaque;
-                case kPremul_SkAlphaType:
-                    return ToColor_S32_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_S32_Raw;
-                default:
-                    return NULL;
-            }
-        case kARGB_4444_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_S4444_Opaque;
-                case kPremul_SkAlphaType:
-                    return ToColor_S4444_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_S4444_Raw;
-                default:
-                    return NULL;
-            }
-        case kRGB_565_SkColorType:
-            return ToColor_S565;
-        case kAlpha_8_SkColorType:
-            return ToColor_SA8;
-        case kRGBA_F16_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_F16_Raw;
-                case kPremul_SkAlphaType:
-                    return ToColor_F16_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_F16_Raw;
-                default:
-                    return NULL;
-            }
-        default:
-            break;
-    }
-    return NULL;
-}
-
 static void ToF16_SA8(void* dst, const void* src, int width) {
     SkASSERT(width > 0);
     uint64_t* d = (uint64_t*)dst;
@@ -694,7 +401,7 @@
     }
 
     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);
     }
 
     return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
@@ -1271,7 +978,7 @@
     if (!bitmapHolder.valid()) return JNI_TRUE;
 
     SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
-    return IsColorSpaceSRGB(colorSpace);
+    return colorSpace == nullptr || colorSpace->isSRGB();
 }
 
 static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
@@ -1330,28 +1037,13 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
 
-    ToColorProc proc = ChooseToColorProc(bitmap);
-    if (NULL == proc) {
-        return 0;
-    }
-    const void* src = bitmap.getAddr(x, y);
-    if (NULL == src) {
-        return 0;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo dstInfo = SkImageInfo::Make(
+            1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
 
-    SkColor dst[1];
-    proc(dst, src, 1);
-
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() != kRGBA_F16_SkColorType &&  !IsColorSpaceSRGB(colorSpace)) {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
-        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
-                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
-                SkAlphaType::kUnpremul_SkAlphaType);
-    }
-
-    return static_cast<jint>(dst[0]);
+    SkColor dst;
+    bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
+    return static_cast<jint>(dst);
 }
 
 static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1360,41 +1052,12 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
 
-    ToColorProc proc = ChooseToColorProc(bitmap);
-    if (NULL == proc) {
-        return;
-    }
-    const void* src = bitmap.getAddr(x, y);
-    if (NULL == src) {
-        return;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo dstInfo = SkImageInfo::Make(
+            width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
 
     jint* dst = env->GetIntArrayElements(pixelArray, NULL);
-    SkColor* d = (SkColor*)dst + offset;
-
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() == kRGBA_F16_SkColorType || IsColorSpaceSRGB(colorSpace)) {
-        while (--height >= 0) {
-            proc(d, src, width);
-            d += stride;
-            src = (void*)((const char*)src + bitmap.rowBytes());
-        }
-    } else {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
-
-        while (--height >= 0) {
-            proc(d, src, width);
-
-            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
-                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
-                    SkAlphaType::kUnpremul_SkAlphaType);
-
-            d += stride;
-            src = (void*)((const char*)src + bitmap.rowBytes());
-        }
-    }
-
+    bitmap.readPixels(dstInfo, dst + offset, stride * 4, x, y);
     env->ReleaseIntArrayElements(pixelArray, dst, 0);
 }
 
@@ -1405,26 +1068,13 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
     SkColor color = static_cast<SkColor>(colorHandle);
-    if (NULL == bitmap.getPixels()) {
-        return;
-    }
 
-    FromColorProc proc = ChooseFromColorProc(bitmap);
-    if (NULL == proc) {
-        return;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo srcInfo = SkImageInfo::Make(
+            1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
+    SkPixmap srcPM(srcInfo, &color, srcInfo.minRowBytes());
 
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() != kRGBA_F16_SkColorType && !IsColorSpaceSRGB(colorSpace)) {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
-        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
-                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
-                SkAlphaType::kUnpremul_SkAlphaType);
-    }
-
-    proc(bitmap.getAddr(x, y), &color, 1, x, y);
-    bitmap.notifyPixelsChanged();
+    bitmap.writePixels(srcPM, x, y);
 }
 
 static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1433,7 +1083,7 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
     GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
-            x, y, width, height, bitmap);
+            x, y, width, height, &bitmap);
 }
 
 static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 9d85cc2..cee3c46 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -102,7 +102,7 @@
     */
     static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
             int srcStride, int x, int y, int width, int height,
-            const SkBitmap& dstBitmap);
+            SkBitmap* dstBitmap);
 
     static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams);
     static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index db3bfe6..eba4c50 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -462,7 +462,7 @@
         return;
     }
 
-    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
+    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, &bitmap)) {
         return;
     }