Bitmap.cpp revision ce217faddb4b40c1b3e698944da1951027080427
1f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#define LOG_TAG "Bitmap"
2f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#include "Bitmap.h"
3f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
40a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv#include "GraphicBuffer.h"
532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkBitmap.h"
632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkPixelRef.h"
732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkImageEncoder.h"
857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III#include "SkImageInfo.h"
99505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkColor.h"
1032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkColorPriv.h"
11ce217faddb4b40c1b3e698944da1951027080427Romain Guy#include "SkColorSpace.h"
12ce217faddb4b40c1b3e698944da1951027080427Romain Guy#include "SkColorSpaceXform.h"
139505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkHalf.h"
14efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy#include "SkMatrix44.h"
159505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkPM4f.h"
169505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkPM4fPriv.h"
1732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "GraphicsJNI.h"
1832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkDither.h"
1932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkUnPreMultiply.h"
2032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkStream.h"
2132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
2232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <binder/Parcel.h>
2332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_os_Parcel.h"
2432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_util_Binder.h"
2532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_nio_utils.h"
2632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "CreateJavaOutputStreamAdaptor.h"
27dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
28c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv#include <hwui/Bitmap.h>
294387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck#include <renderthread/RenderProxy.h>
3032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
31ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
32ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
3332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <jni.h>
34ce217faddb4b40c1b3e698944da1951027080427Romain Guy#include <string.h>
3539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <memory>
3639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <string>
3732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#define DEBUG_PARCEL 0
398cee7c17119b204be88860feb812f2374d0de732Riley Andrews#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
40a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
41c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass   gBitmap_class;
42c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID gBitmap_nativePtr;
43c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_constructorMethodID;
44c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_reinitMethodID;
45c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_getAllocationByteCountMethodID;
46c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
47f29ed28c7b878ef28058bc730715d0d32445bc57John Recknamespace android {
48f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
49c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvclass BitmapWrapper {
50f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
51c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper(Bitmap* bitmap)
52c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        : mBitmap(bitmap) { }
53c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
54c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void freePixels() {
55c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mInfo = mBitmap->info();
56c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
57c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mAllocationSize = mBitmap->getAllocationByteCount();
58c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mRowBytes = mBitmap->rowBytes();
59c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mGenerationId = mBitmap->getGenerationID();
6015a108550e3d74b406927d85c8e69018761adf49sergeyv        mIsHardware = mBitmap->isHardware();
61c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap.reset();
62f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
63f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
64c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool valid() {
65fc9999505a36c66892d7ccce85187936105f4f36sergeyv        return mBitmap;
66f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
67f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
68aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    Bitmap& bitmap() {
69aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        assertValid();
70aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return *mBitmap;
71aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
72c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
73c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void assertValid() {
74c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
75c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
76c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
77c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void getSkBitmap(SkBitmap* outBitmap) {
78c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
79c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->getSkBitmap(outBitmap);
80c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
810781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
82c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool hasHardwareMipMap() {
83c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
84c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->hasHardwareMipMap();
85c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
86f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mHasHardwareMipMap;
87f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
88f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
89f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void setHasHardwareMipMap(bool hasMipMap) {
90c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
91c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setHasHardwareMipMap(hasMipMap);
92f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
93f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
94c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void setAlphaType(SkAlphaType alphaType) {
95c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
96c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setAlphaType(alphaType);
97f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
98f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
99c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    const SkImageInfo& info() {
100c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
101c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->info();
102c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
103c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mInfo;
104f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
105f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
106c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t getAllocationByteCount() const {
107c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
108c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getAllocationByteCount();
109c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
110c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mAllocationSize;
111f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
112f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
113c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t rowBytes() const {
114c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
115c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->rowBytes();
116c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
117c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mRowBytes;
118c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
119f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
120c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t getGenerationID() const {
121c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
122c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getGenerationID();
123c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
124c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mGenerationId;
125f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
126c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
12715a108550e3d74b406927d85c8e69018761adf49sergeyv    bool isHardware() {
12815a108550e3d74b406927d85c8e69018761adf49sergeyv        if (mBitmap) {
12915a108550e3d74b406927d85c8e69018761adf49sergeyv            return mBitmap->isHardware();
13015a108550e3d74b406927d85c8e69018761adf49sergeyv        }
13115a108550e3d74b406927d85c8e69018761adf49sergeyv        return mIsHardware;
13215a108550e3d74b406927d85c8e69018761adf49sergeyv    }
13315a108550e3d74b406927d85c8e69018761adf49sergeyv
134c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    ~BitmapWrapper() { }
135c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
136c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvprivate:
137c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> mBitmap;
138c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkImageInfo mInfo;
139c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool mHasHardwareMipMap;
140c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mAllocationSize;
141c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mRowBytes;
142c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t mGenerationId;
14315a108550e3d74b406927d85c8e69018761adf49sergeyv    bool mIsHardware;
144f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
145f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
146f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// Convenience class that does not take a global ref on the pixels, relying
147f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// on the caller already having a local JNI ref
148f29ed28c7b878ef28058bc730715d0d32445bc57John Reckclass LocalScopedBitmap {
149f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
150c6baf563ba6aa207a48317c177b29f1d2b70cf3dChih-Hung Hsieh    explicit LocalScopedBitmap(jlong bitmapHandle)
151c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
152f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
153c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* operator->() {
154c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper;
155f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
156f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
157f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* pixels() {
158aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return mBitmapWrapper->bitmap().pixels();
159f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
160f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
161f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool valid() {
162c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper && mBitmapWrapper->valid();
163f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
164f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
165f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprivate:
166c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* mBitmapWrapper;
167f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
168f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
169c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvnamespace bitmap {
170c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
171c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
172c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
173c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
174c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // irrelevant. This just tests to ensure that the SkAlphaType is not
175c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // opposite of isPremultiplied.
176c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isPremultiplied) {
177c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
178c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    } else {
179c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
180c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
181c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
182c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
183c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
184c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        bool isPremultiplied)
185c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
186c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
187c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
188c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    assert_premultiplied(info, isPremultiplied);
189c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
190c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
191c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            info.width(), info.height(), isPremultiplied);
192c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
193c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
194c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvint getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
195c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
196c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
197c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
198c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
199c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvjobject createBitmap(JNIEnv* env, Bitmap* bitmap,
200c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
201c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int density) {
202c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
203c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
204c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
205c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
206c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    assert_premultiplied(bitmap->info(), isPremultiplied);
207c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
208c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
209c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
210c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
211c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
212c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (env->ExceptionCheck() != 0) {
213c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        ALOGE("*** Uncaught exception returned from Java call!\n");
214c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        env->ExceptionDescribe();
215c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
216c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return obj;
217c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
218c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
219c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
220c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap bitmap(bitmapHandle);
221c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->getSkBitmap(outBitmap);
222c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
223c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
224aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyvBitmap& toBitmap(JNIEnv* env, jobject bitmap) {
225c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env);
226c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(bitmap);
227c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
228c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
229c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
230c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return localBitmap->bitmap();
231c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
232c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
2335fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyvBitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
2345fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    SkASSERT(env);
2355fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
2365fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    return localBitmap->bitmap();
2375fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv}
2385fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv
23900799f760d6956fc54ee1763427f8196fcb3696dJohn Reckvoid imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
24000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(info);
24100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env);
24200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(bitmap);
24300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
24400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
24500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    LocalScopedBitmap localBitmap(bitmapHandle);
24600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
24700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    const SkImageInfo& imageInfo = localBitmap->info();
24800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->width = imageInfo.width();
24900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->height = imageInfo.height();
25000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->stride = localBitmap->rowBytes();
25100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->flags = 0;
25200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    switch (imageInfo.colorType()) {
25300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kN32_SkColorType:
25400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
25500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
25600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kRGB_565_SkColorType:
25700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
25800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
25900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kARGB_4444_SkColorType:
26000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
26100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
26200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kAlpha_8_SkColorType:
26300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_A_8;
26400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
26500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        default:
26600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_NONE;
26700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
26800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    }
26900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck}
27000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
27100799f760d6956fc54ee1763427f8196fcb3696dJohn Reckvoid* lockPixels(JNIEnv* env, jobject bitmap) {
27200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env);
27300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(bitmap);
27400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
27500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
27600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
27700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    LocalScopedBitmap localBitmap(bitmapHandle);
27800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    if (!localBitmap->valid()) return nullptr;
27900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
28000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkPixelRef& pixelRef = localBitmap->bitmap();
28100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.lockPixels();
28200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    if (!pixelRef.pixels()) {
28300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        pixelRef.unlockPixels();
28400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        return nullptr;
28500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    }
28600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.ref();
28700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    return pixelRef.pixels();
28800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck}
28900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
29000799f760d6956fc54ee1763427f8196fcb3696dJohn Reckbool unlockPixels(JNIEnv* env, jobject bitmap) {
29100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env);
29200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(bitmap);
29300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
29400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
29500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
29600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    LocalScopedBitmap localBitmap(bitmapHandle);
29700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    if (!localBitmap->valid()) return false;
29800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
29900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkPixelRef& pixelRef = localBitmap->bitmap();
30000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.notifyPixelsChanged();
30100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.unlockPixels();
30200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.unref();
30300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    return true;
30400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck}
30500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
306c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace bitmap
307c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
308c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace android
309c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
310c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android;
311c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android::bitmap;
312c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
31332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
31432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// Conversions to/from SkColor, for get/setPixels, and the create method, which
31532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// is basically like setPixels
31632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
31732054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
31832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              int x, int y);
31932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
3209505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void FromColor_F16(void* dst, const SkColor src[], int width,
3219505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                          int, int) {
3229505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* d = (uint64_t*)dst;
3239505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
3249505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    for (int i = 0; i < width; i++) {
3259505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
3269505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
3279505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
3289505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
3299505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
3309505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                          int, int) {
3319505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* d = (uint64_t*)dst;
3329505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
3339505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    for (int i = 0; i < width; i++) {
3349505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        const float* color = SkColor4f::FromColor(*src++).vec();
3359505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
3369505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        for (int i = 0; i < 4; ++i) {
3379505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            scratch[i] = SkFloatToHalf(color[i]);
3389505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        }
3399505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
3409505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
3419505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
34232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32(void* dst, const SkColor src[], int width,
34332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
34432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
34532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
34632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
34732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPreMultiplyColor(*src++);
34832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
34932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
35032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
35132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
35232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
35346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    // Needed to thwart the unreachable code detection from clang.
35446d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
35546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert
35632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // SkColor's ordering may be different from SkPMColor
35746d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    if (sk_color_ne_zero) {
35832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        memcpy(dst, src, width * sizeof(SkColor));
35932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
36032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
36132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
36232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // order isn't same, repack each pixel manually
36332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
36432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
36532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
36632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
36732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   SkColorGetG(c), SkColorGetB(c));
36832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
36932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
37032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D565(void* dst, const SkColor src[], int width,
37232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           int x, int y) {
37332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    uint16_t* d = (uint16_t*)dst;
37432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_565_SCAN(y);
37632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
37732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
37832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
37932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                DITHER_VALUE(x));
38032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
38132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
38232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444(void* dst, const SkColor src[], int width,
38432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
38532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
38632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
38832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
38932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPreMultiplyColor(*src++);
39032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
39132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
39232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
39332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
39432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
39632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
39732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
39832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
40032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
40132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
40232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
40332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
40432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
40532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            SkColorGetG(c), SkColorGetB(c));
40632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
40732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
40832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
40932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
41032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4116260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
4126260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    uint8_t* d = (uint8_t*)dst;
4136260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
4146260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    for (int stop = x + width; x < stop; x++) {
4156260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *d++ = SkColorGetA(*src++);
4166260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    }
4176260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
4186260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
41932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
42057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
42157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    switch (bitmap.colorType()) {
42257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kN32_SkColorType:
42357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
42457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kARGB_4444_SkColorType:
42557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
42657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    FromColor_D4444_Raw;
42757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kRGB_565_SkColorType:
42832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return FromColor_D565;
4296260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
4306260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return FromColor_DA8;
4319505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        case kRGBA_F16_SkColorType:
4329505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
43332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
43432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
43532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
43632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
43732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
43832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikbool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
44057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
44132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkAutoLockPixels alp(dstBitmap);
44232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    void* dst = dstBitmap.getPixels();
44357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    FromColorProc proc = ChooseFromColorProc(dstBitmap);
44432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == dst || NULL == proc) {
44632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return false;
44732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
44832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const jint* array = env->GetIntArrayElements(srcColors, NULL);
45032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkColor* src = (const SkColor*)array + srcOffset;
45132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
45232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // reset to to actual choice from caller
45332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dst = dstBitmap.getAddr(x, y);
454ce217faddb4b40c1b3e698944da1951027080427Romain Guy
455ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = dstBitmap.colorSpace();
456ce217faddb4b40c1b3e698944da1951027080427Romain Guy    if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
457ce217faddb4b40c1b3e698944da1951027080427Romain Guy        // now copy/convert each scanline
458ce217faddb4b40c1b3e698944da1951027080427Romain Guy        for (int y = 0; y < height; y++) {
459ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(dst, src, width, x, y);
460ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src += srcStride;
461ce217faddb4b40c1b3e698944da1951027080427Romain Guy            dst = (char*)dst + dstBitmap.rowBytes();
462ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
463ce217faddb4b40c1b3e698944da1951027080427Romain Guy    } else {
464ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
465ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
466ce217faddb4b40c1b3e698944da1951027080427Romain Guy
467ce217faddb4b40c1b3e698944da1951027080427Romain Guy        std::unique_ptr<SkColor[]> row(new SkColor[width]);
468ce217faddb4b40c1b3e698944da1951027080427Romain Guy
469ce217faddb4b40c1b3e698944da1951027080427Romain Guy        // now copy/convert each scanline
470ce217faddb4b40c1b3e698944da1951027080427Romain Guy        for (int y = 0; y < height; y++) {
471ce217faddb4b40c1b3e698944da1951027080427Romain Guy            memcpy(row.get(), src, sizeof(SkColor) * width);
472ce217faddb4b40c1b3e698944da1951027080427Romain Guy            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
473ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
474ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkAlphaType::kUnpremul_SkAlphaType);
475ce217faddb4b40c1b3e698944da1951027080427Romain Guy
476ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(dst, row.get(), width, x, y);
477ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src += srcStride;
478ce217faddb4b40c1b3e698944da1951027080427Romain Guy            dst = (char*)dst + dstBitmap.rowBytes();
479ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
48032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
48132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
48232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dstBitmap.notifyPixelsChanged();
48332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4849505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
48532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return true;
48632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
48732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
48832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//////////////////// ToColor procs
48932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
49032054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
49132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            SkColorTable*);
49232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4939505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
4949505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                              SkColorTable*) {
4959505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    SkASSERT(width > 0);
4969505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* s = (uint64_t*)src;
4979505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    do {
4989505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
4999505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    } while (--width != 0);
5009505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
5019505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
5029505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
5039505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                            SkColorTable*) {
5049505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    SkASSERT(width > 0);
5059505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* s = (uint64_t*)src;
5069505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    do {
5079505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
5089505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    } while (--width != 0);
5099505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
5109505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
51132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
51232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
51332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
51432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
51532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
51632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
51732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
51832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
51932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
52032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
52132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
52232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
52332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
52432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
52532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
52632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
52732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
52832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
52932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
53032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
53132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
53232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable*) {
53332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
53432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
53532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
53632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
53732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
53832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
53932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
54032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
54132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
54232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
54332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
54432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
54532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
54632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
54732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
54832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
54932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
55032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
55132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
55232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
55332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
55432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
55532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
55632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
55732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
55832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
55932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
56032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
56132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
56232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
56332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 SkColorTable*) {
56432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
56532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
56632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
56732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
56832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
56932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
57032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
57132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
57232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
57332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S565(SkColor dst[], const void* src, int width,
57432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                         SkColorTable*) {
57532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
57632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint16_t* s = (const uint16_t*)src;
57732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
57832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        uint16_t c = *s++;
57932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
58032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkPacked16ToB32(c));
58132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
58232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
58332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
58432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
58532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
58632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
58732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
58871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
58932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
59032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
59132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
59232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
59332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
59432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
59532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
59632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
59732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
59871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
59932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
60032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
60132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
60232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
60332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
60432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
60532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
60632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
60732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable* ctable) {
60832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
60932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
61071487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
61132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
61232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
61332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
61432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
61532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
61632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
61732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
6186260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
6196260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    SkASSERT(width > 0);
6206260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    const uint8_t* s = (const uint8_t*)src;
6216260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    do {
6226260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        uint8_t c = *s++;
6236260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *dst++ = SkColorSetARGB(c, c, c, c);
6246260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    } while (--width != 0);
6256260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
6266260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
62732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
62857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic ToColorProc ChooseToColorProc(const SkBitmap& src) {
629b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    switch (src.colorType()) {
630b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kN32_SkColorType:
63157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
63257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
63357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Opaque;
63457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
63557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Alpha;
63657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
63757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Raw;
63857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
63957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
64057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
641b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kARGB_4444_SkColorType:
64257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
64357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
64457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Opaque;
64557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
64657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Alpha;
64757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
64857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Raw;
64957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
65057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
65157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
652b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kRGB_565_SkColorType:
65332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return ToColor_S565;
654b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kIndex_8_SkColorType:
65532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            if (src.getColorTable() == NULL) {
65632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                return NULL;
65732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            }
65857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
65957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
66057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Opaque;
66157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
66257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Alpha;
66357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
66457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Raw;
66557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
66657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
66757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
6686260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
6696260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return ToColor_SA8;
6709505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        case kRGBA_F16_SkColorType:
6719505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            switch (src.alphaType()) {
6729505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kOpaque_SkAlphaType:
6739505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Raw;
6749505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kPremul_SkAlphaType:
6759505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Alpha;
6769505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kUnpremul_SkAlphaType:
6779505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Raw;
6789505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                default:
6799505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return NULL;
6809505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            }
68132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
68232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
68332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
68432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
68532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
68632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
68732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
68832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
68932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic int getPremulBitmapCreateFlags(bool isMutable) {
691c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
692c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
69332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return flags;
69432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
69532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
69732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint offset, jint stride, jint width, jint height,
69832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint configHandle, jboolean isMutable) {
6991103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
70032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != jColors) {
70132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        size_t n = env->GetArrayLength(jColors);
70232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (n < SkAbs32(stride) * (size_t)height) {
70332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            doThrowAIOOBE(env);
70432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return NULL;
70532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
70632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
70732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
70832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // ARGB_4444 is a deprecated format, convert automatically to 8888
709b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kARGB_4444_SkColorType) {
710b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        colorType = kN32_SkColorType;
71132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
71232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
71332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkBitmap bitmap;
714253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
7159505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            GraphicsJNI::colorSpaceForType(colorType)));
71632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
717c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
718f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!nativeBitmap) {
71932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
72032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
72132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
72232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (jColors != NULL) {
7239505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
72432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
72532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
726c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
72732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
72832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
72932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
73032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           jint dstConfigHandle, jboolean isMutable) {
731f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
732c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
73305126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv    if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
73405126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
73505126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        if (!bitmap.get()) {
73605126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv            return NULL;
73705126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        }
738656117bed2fc1937bcebd615898924ed57c48979sergeyv        return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
73905126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv    }
74005126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv
7411103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
7424508218850faedea95371188da587b6734f5f3dasergeyv    SkBitmap result;
7434508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
74432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
745f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!src.copyTo(&result, dstCT, &allocator)) {
74632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
74732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
748c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
749c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
75032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
75132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
752c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
753721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    SkBitmap result;
754721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
755721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    AshmemPixelAllocator allocator(env);
756a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    if (!src.copyTo(&result, dstCT, &allocator)) {
757721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        return NULL;
758721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    }
759c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
760c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmap->setImmutable();
761c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return bitmap;
762a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
763a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
764a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
765a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
766c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
767a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = src.colorType();
768c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
769c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
770a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    return ret;
771a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
772a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
773a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
774a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
775c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
776a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
777c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
778c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
779721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    return ret;
780721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews}
781721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
782c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic void Bitmap_destruct(BitmapWrapper* bitmap) {
783c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    delete bitmap;
78432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
78532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
786775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
787775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
788775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler}
789775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
79032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
791f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
792f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->freePixels();
79332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
79432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
79532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
79632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
7974508218850faedea95371188da587b6734f5f3dasergeyv        jint width, jint height, jint configHandle, jboolean requestPremul) {
798f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
799c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->assertValid();
8001103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
80117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III
80217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    // ARGB_4444 is a deprecated format, convert automatically to 8888
80317a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    if (colorType == kARGB_4444_SkColorType) {
80417a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        colorType = kN32_SkColorType;
80517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
8064508218850faedea95371188da587b6734f5f3dasergeyv    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
8074508218850faedea95371188da587b6734f5f3dasergeyv    if (requestedSize > bitmap->getAllocationByteCount()) {
80832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // done in native as there's no way to get BytesPerPixel in Java
80932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowIAE(env, "Bitmap not large enough to support new configuration");
81032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
81132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
81217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    SkAlphaType alphaType;
813f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().colorType() != kRGB_565_SkColorType
814f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
81517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // If the original bitmap was set to opaque, keep that setting, unless it
81617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // was 565, which is required to be opaque.
81717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = kOpaque_SkAlphaType;
81817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    } else {
81917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // Otherwise respect the premultiplied request.
82017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
82117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
822aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
8237d5219fb505ff1b178910cda25a40154e7d4d09asergeyv            sk_ref_sp(bitmap->info().colorSpace())));
82432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
82532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
82632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// These must match the int values in Bitmap.java
82732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikenum JavaEncodeFormat {
82832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kJPEG_JavaEncodeFormat = 0,
82932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kPNG_JavaEncodeFormat = 1,
83032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kWEBP_JavaEncodeFormat = 2
83132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
83232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
83332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
83432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jint format, jint quality,
83532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jobject jstream, jbyteArray jstorage) {
83610219fb261606fcc71c607167b28295b4578a10dHal Canary    SkEncodedImageFormat fm;
83732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    switch (format) {
83832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kJPEG_JavaEncodeFormat:
83910219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kJPEG;
84032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kPNG_JavaEncodeFormat:
84210219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kPNG;
84332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kWEBP_JavaEncodeFormat:
84510219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kWEBP;
84632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    default:
84832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
84932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
85032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
85110219fb261606fcc71c607167b28295b4578a10dHal Canary    LocalScopedBitmap bitmap(bitmapHandle);
852f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap.valid()) {
853f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
854f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
85532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
856f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
857f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!strm.get()) {
858f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
859f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
86032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
86110219fb261606fcc71c607167b28295b4578a10dHal Canary    SkBitmap skbitmap;
86210219fb261606fcc71c607167b28295b4578a10dHal Canary    bitmap->getSkBitmap(&skbitmap);
86310219fb261606fcc71c607167b28295b4578a10dHal Canary    return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
86432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
86532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
86632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
867f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
868f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap skBitmap;
869f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->getSkBitmap(&skBitmap);
870f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    skBitmap.eraseColor(color);
87132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
87232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
87332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
874f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
87532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(bitmap->rowBytes());
87632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
87732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
87832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
879f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
88015a108550e3d74b406927d85c8e69018761adf49sergeyv    if (bitmap->isHardware()) {
88119b4b019169424d62bf3edc40b9560984206cf80sergeyv        return GraphicsJNI::hardwareLegacyBitmapConfig();
88219b4b019169424d62bf3edc40b9560984206cf80sergeyv    }
883f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
88432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
88532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
88632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
887f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
888c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return static_cast<jint>(bitmap->getGenerationID());
88932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
89032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
89157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
892f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
893f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
89457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        return JNI_TRUE;
89557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
89657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    return JNI_FALSE;
89757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
89857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
89932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
900f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
901f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
90232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
90332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
90457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
90557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean hasAlpha, jboolean requestPremul) {
906f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
90757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    if (hasAlpha) {
9080781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(
909f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
91032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } else {
9110781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(kOpaque_SkAlphaType);
91257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
91357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
91457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
91557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
91657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean isPremul) {
917f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
918f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap->info().isOpaque()) {
91957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        if (isPremul) {
9200781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kPremul_SkAlphaType);
92157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        } else {
9220781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kUnpremul_SkAlphaType);
92357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        }
92432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
92532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
92632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
92732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
928f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
92932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
93032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
93132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
93232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
93332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jboolean hasMipMap) {
934f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
93532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    bitmap->setHasHardwareMipMap(hasMipMap);
93632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
93732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
93832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
93932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
94032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
94132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
94232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("-------- unparcel parcel is NULL\n");
94332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
94432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
94532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
94632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
94732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
948b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const bool        isMutable = p->readInt32() != 0;
949b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkColorType colorType = (SkColorType)p->readInt32();
950b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
9515acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    const uint32_t    colorSpaceSize = p->readUint32();
9525acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    sk_sp<SkColorSpace> colorSpace;
9535acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    if (kRGBA_F16_SkColorType == colorType) {
9545acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        colorSpace = SkColorSpace::MakeSRGBLinear();
9555acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    } else if (colorSpaceSize > 0) {
9565acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        colorSpace = SkColorSpace::Deserialize(p->readInplace(colorSpaceSize), colorSpaceSize);
9575acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    }
958b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         width = p->readInt32();
959b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         height = p->readInt32();
960b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         rowBytes = p->readInt32();
961b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         density = p->readInt32();
962b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed
963b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (kN32_SkColorType != colorType &&
9649505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            kRGBA_F16_SkColorType != colorType &&
965b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kRGB_565_SkColorType != colorType &&
966b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kARGB_4444_SkColorType != colorType &&
967b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kIndex_8_SkColorType != colorType &&
968b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kAlpha_8_SkColorType != colorType) {
969b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
97032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
97132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
97232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
973ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
9749505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
9759505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            rowBytes)) {
976ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        return NULL;
977ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    }
97832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
97932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColorTable* ctable = NULL;
980b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kIndex_8_SkColorType) {
98132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int count = p->readInt32();
982ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        if (count < 0 || count > 256) {
983ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
984ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // inclusive.
985ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            return NULL;
986ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        }
98732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (count > 0) {
98832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            size_t size = count * sizeof(SkPMColor);
98932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
990ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            if (src == NULL) {
991ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III                return NULL;
992ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            }
99332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            ctable = new SkColorTable(src, count);
99432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
99532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
99632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
997a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Read the bitmap blob.
998a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap->getSize();
999a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::ReadableBlob blob;
1000a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status = p->readBlob(size, &blob);
1001a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
100232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkSafeUnref(ctable);
1003a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not read bitmap blob.");
100432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
100532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
100632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1007a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Map the bitmap in place from the ashmem region if possible otherwise copy.
1008c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap;
10098cee7c17119b204be88860feb812f2374d0de732Riley Andrews    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
1010a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1011a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
1012a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "(fds %s)",
1013a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                isMutable ? "mutable" : "immutable",
1014a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                blob.isMutable() ? "mutable" : "immutable",
1015a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
1016a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1017a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Dup the file descriptor so we can keep a reference to it after the Parcel
1018a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // is disposed.
1019a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        int dupFd = dup(blob.fd());
1020a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (dupFd < 0) {
1021211abad3b92b70dd094949c79f67e686c940fa0cErik Wolsheimer            ALOGE("Error allocating dup fd. Error:%d", errno);
1022a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1023a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            SkSafeUnref(ctable);
1024a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate dup blob fd.");
1025a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
102639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1027a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1028a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Map the pixels in place and take ownership of the ashmem region.
1029c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
1030c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
1031a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
1032a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
1033a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            close(dupFd);
1034a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1035a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate ashmem pixel ref.");
1036a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
103739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1038a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1039a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Clear the blob handle, don't release it.
1040a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.clear();
1041a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
1042a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1043a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (blob.fd() >= 0) {
1044a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
1045a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "from immutable blob (fds %s)",
1046a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
1047a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        } else {
1048a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
1049a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "(fds %s)",
1050a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    blob.isMutable() ? "mutable" : "immutable",
1051a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
105239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1053a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1054a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1055a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Copy the pixels into a new buffer.
1056c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
1057a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
1058a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
1059a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1060a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate java pixel ref.");
1061a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
106239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1063a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->lockPixels();
1064a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(bitmap->getPixels(), blob.data(), size);
1065a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->unlockPixels();
1066a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1067a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Release the blob handle.
1068a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.release();
106939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
1070a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1071c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(),
1072a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
1073a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown}
107439d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
107532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
107632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jlong bitmapHandle,
107732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jboolean isMutable, jint density,
107832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jobject parcel) {
107932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
108032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("------- writeToParcel null parcel\n");
108132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
108232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
108332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
108432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1085f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
108639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
1087c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
1088c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmapWrapper->getSkBitmap(&bitmap);
108932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
109032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(isMutable);
1091f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.colorType());
1092f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.alphaType());
10935acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
10945acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
10955acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        sk_sp<SkData> data = colorSpace->serialize();
10965acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        size_t size = data->size();
10975acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        p->writeUint32(size);
10985acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        if (size > 0) {
10995acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy            p->write(data->data(), size);
11005acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        }
11015acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    } else {
11025acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        p->writeUint32(0);
11035acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    }
1104f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.width());
1105f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.height());
1106f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.rowBytes());
110732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(density);
110832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1109f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap.colorType() == kIndex_8_SkColorType) {
111066ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        // The bitmap needs to be locked to access its color table.
111166ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        SkAutoLockPixels alp(bitmap);
1112f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ctable = bitmap.getColorTable();
111332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ctable != NULL) {
111432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            int count = ctable->count();
111532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(count);
111632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
111771487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed                   ctable->readColors(), count * sizeof(SkPMColor));
111832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        } else {
111932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(0);   // indicate no ctable
112032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
112132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
112232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1123a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Transfer the underlying ashmem region if we have one and it's immutable.
1124a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status;
1125aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    int fd = bitmapWrapper->bitmap().getAshmemFd();
1126a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (fd >= 0 && !isMutable && p->allowFds()) {
1127a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1128a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1129a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "immutable blob (fds %s)",
1130a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
1131a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1132a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1133a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        status = p->writeDupImmutableBlobFileDescriptor(fd);
1134a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (status) {
1135a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not write bitmap blob file descriptor.");
113639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews            return JNI_FALSE;
113739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1138a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_TRUE;
1139a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
114032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1141a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Copy the bitmap to a new blob.
1142a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bool mutableCopy = isMutable;
1143a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1144a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1145a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            isMutable ? "mutable" : "immutable",
1146a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            mutableCopy ? "mutable" : "immutable",
1147a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            p->allowFds() ? "allowed" : "forbidden");
1148a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1149a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1150a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap.getSize();
1151a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::WritableBlob blob;
1152a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    status = p->writeBlob(size, mutableCopy, &blob);
1153a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
1154a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not copy bitmap to parcel blob.");
1155a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_FALSE;
115639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
1157a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1158a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.lockPixels();
1159a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    const void* pSrc =  bitmap.getPixels();
1160a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (pSrc == NULL) {
1161a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memset(blob.data(), 0, size);
1162a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
1163a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(blob.data(), pSrc, size);
1164a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
1165a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.unlockPixels();
1166a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1167a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    blob.release();
116832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
116932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
117032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
117132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
117232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jlong srcHandle, jlong paintHandle,
117332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jintArray offsetXY) {
1174f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
1175c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
11766ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
117732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkIPoint  offset;
1178f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap dst;
11794508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
118032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1181f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    src.extractAlpha(&dst, paint, &allocator, &offset);
118232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // If Skia can't allocate pixels for destination bitmap, it resets
118332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // it, that is set its pixels buffer to NULL, and zero width and height.
1184f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
118532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowOOME(env, "failed to allocate pixels for alpha");
118632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
118732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
118832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
118932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int* array = env->GetIntArrayElements(offsetXY, NULL);
119032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[0] = offset.fX;
119132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[1] = offset.fY;
119232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        env->ReleaseIntArrayElements(offsetXY, array, 0);
119332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
119432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1195c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, allocator.getStorageObjAndReset(),
1196f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(true));
119732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
119832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
119932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
120032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1201efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guystatic jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
1202efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    LocalScopedBitmap bitmapHolder(bitmapHandle);
1203efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!bitmapHolder.valid()) return JNI_TRUE;
1204efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1205efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1206ce217faddb4b40c1b3e698944da1951027080427Romain Guy    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
1207efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy}
1208efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1209efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guystatic jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
1210efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy        jfloatArray xyzArray, jfloatArray paramsArray) {
1211efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1212efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    LocalScopedBitmap bitmapHolder(bitmapHandle);
1213efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!bitmapHolder.valid()) return JNI_FALSE;
1214efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1215efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1216efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (colorSpace == nullptr) return JNI_FALSE;
1217efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1218efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
1219efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
1220efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1221efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
1222efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[0] = xyzMatrix.getFloat(0, 0);
1223efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[1] = xyzMatrix.getFloat(1, 0);
1224efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[2] = xyzMatrix.getFloat(2, 0);
1225efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[3] = xyzMatrix.getFloat(0, 1);
1226efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[4] = xyzMatrix.getFloat(1, 1);
1227efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[5] = xyzMatrix.getFloat(2, 1);
1228efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[6] = xyzMatrix.getFloat(0, 2);
1229efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[7] = xyzMatrix.getFloat(1, 2);
1230efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[8] = xyzMatrix.getFloat(2, 2);
1231efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
1232efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1233efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkColorSpaceTransferFn transferParams;
1234efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
1235efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1236efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
1237efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[0] = transferParams.fA;
1238efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[1] = transferParams.fB;
1239efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[2] = transferParams.fC;
1240efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[3] = transferParams.fD;
1241efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[4] = transferParams.fE;
1242efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[5] = transferParams.fF;
1243efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[6] = transferParams.fG;
1244efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    env->ReleaseFloatArrayElements(paramsArray, params, 0);
1245efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1246efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    return JNI_TRUE;
1247efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy}
1248efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1249efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy///////////////////////////////////////////////////////////////////////////////
1250efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
125132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
125257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y) {
1253f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1254c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1255f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
125632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1257f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
125832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
125932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
126032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1261f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
126232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
126332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
126432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
126532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
126632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor dst[1];
1267f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(dst, src, 1, bitmap.getColorTable());
1268ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1269ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
1270ce217faddb4b40c1b3e698944da1951027080427Romain Guy    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1271ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
1272ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1273ce217faddb4b40c1b3e698944da1951027080427Romain Guy        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
1274ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
1275ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkAlphaType::kUnpremul_SkAlphaType);
1276ce217faddb4b40c1b3e698944da1951027080427Romain Guy    }
1277ce217faddb4b40c1b3e698944da1951027080427Romain Guy
127832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(dst[0]);
127932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
128032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
128132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
128232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
128357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1284f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1285c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1286f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
128732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1288f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
128932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
129032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
129132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1292f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
129332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
129432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
129532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
129632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1297f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkColorTable* ctable = bitmap.getColorTable();
129832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
129932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor* d = (SkColor*)dst + offset;
1300ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1301ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
1302ce217faddb4b40c1b3e698944da1951027080427Romain Guy    if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1303ce217faddb4b40c1b3e698944da1951027080427Romain Guy        while (--height >= 0) {
1304ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(d, src, width, ctable);
1305ce217faddb4b40c1b3e698944da1951027080427Romain Guy            d += stride;
1306ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src = (void*)((const char*)src + bitmap.rowBytes());
1307ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
1308ce217faddb4b40c1b3e698944da1951027080427Romain Guy    } else {
1309ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
1310ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1311ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1312ce217faddb4b40c1b3e698944da1951027080427Romain Guy        while (--height >= 0) {
1313ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(d, src, width, ctable);
1314ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1315ce217faddb4b40c1b3e698944da1951027080427Romain Guy            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
1316ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
1317ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkAlphaType::kUnpremul_SkAlphaType);
1318ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1319ce217faddb4b40c1b3e698944da1951027080427Romain Guy            d += stride;
1320ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src = (void*)((const char*)src + bitmap.rowBytes());
1321ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
132232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1323ce217faddb4b40c1b3e698944da1951027080427Romain Guy
132432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(pixelArray, dst, 0);
132532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
132632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
132732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
132832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
132932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
133057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint colorHandle) {
1331f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1332c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
133332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor color = static_cast<SkColor>(colorHandle);
1334f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1335f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bitmap.getPixels()) {
133632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
133732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
133832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1339f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    FromColorProc proc = ChooseFromColorProc(bitmap);
134032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
134132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
134232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
134332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1344ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
1345ce217faddb4b40c1b3e698944da1951027080427Romain Guy    if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1346ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
1347ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
1348ce217faddb4b40c1b3e698944da1951027080427Romain Guy        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
1349ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
1350ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkAlphaType::kUnpremul_SkAlphaType);
1351ce217faddb4b40c1b3e698944da1951027080427Romain Guy    }
1352ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1353f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1354f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap.notifyPixelsChanged();
135532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
135632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
135732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
135832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
135957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1360f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1361c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
136232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1363f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            x, y, width, height, bitmap);
136432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
136532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
136632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
136732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                      jlong bitmapHandle, jobject jbuffer) {
1368f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1369c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1370f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1371f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getPixels();
137232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
137332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != src) {
137432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
137532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
137632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1377f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(abp.pointer(), src, bitmap.getSize());
137832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
137932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
138032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
138132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
138232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                        jlong bitmapHandle, jobject jbuffer) {
1383f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1384c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1385f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1386f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* dst = bitmap.getPixels();
138732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
138832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != dst) {
138932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
139032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1391f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(dst, abp.pointer(), bitmap.getSize());
1392f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bitmap.notifyPixelsChanged();
139332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
139432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
139532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1396795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craikstatic jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
1397f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm0;
1398f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm1;
13991eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
14001eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    LocalScopedBitmap bitmap0(bm0Handle);
14011eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    LocalScopedBitmap bitmap1(bm1Handle);
14021eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
14031eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // Paying the price for making Hardware Bitmap as Config:
14041eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // later check for colorType will pass successfully,
14051eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // because Hardware Config internally may be RGBA8888 or smth like that.
140615a108550e3d74b406927d85c8e69018761adf49sergeyv    if (bitmap0->isHardware() != bitmap1->isHardware()) {
14071eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv        return JNI_FALSE;
14081eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    }
14091eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
14101eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    bitmap0->bitmap().getSkBitmap(&bm0);
14111eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    bitmap1->bitmap().getSkBitmap(&bm1);
1412795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik    if (bm0.width() != bm1.width()
1413795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.height() != bm1.height()
1414795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.colorType() != bm1.colorType()
1415795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.alphaType() != bm1.alphaType()
1416795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
141732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
141832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
141932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1420f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp0(bm0);
1421f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp1(bm1);
142232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
142332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // if we can't load the pixels, return false
1424f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
142532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
142632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
142732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1428f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bm0.colorType() == kIndex_8_SkColorType) {
1429f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct0 = bm0.getColorTable();
1430f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct1 = bm1.getColorTable();
143132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (NULL == ct0 || NULL == ct1) {
143232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
143332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
143432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ct0->count() != ct1->count()) {
143532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
143632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
143732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
143832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        const size_t size = ct0->count() * sizeof(SkPMColor);
143971487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
144032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
144132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
144232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
144332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
144432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now compare each scanline. We can't do the entire buffer at once,
144532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // since we don't care about the pixel values that might extend beyond
144632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // the width (since the scanline might be larger than the logical width)
1447f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const int h = bm0.height();
1448f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const size_t size = bm0.width() * bm0.bytesPerPixel();
144932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < h; y++) {
145053001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
145153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
145253001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
145353001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
145453001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // to warn user those 2 unrecognized config bitmaps may be different.
1455f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm0Addr = bm0.getAddr(0, y);
1456f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm1Addr = bm1.getAddr(0, y);
145753001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
145853001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if(bm0Addr == NULL || bm1Addr == NULL) {
145953001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen            return JNI_FALSE;
146053001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        }
146153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
146253001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
146332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
146432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
146532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
146632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
146732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
146832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
14694387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reckstatic void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
14704387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    LocalScopedBitmap bitmapHandle(bitmapPtr);
14714387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    if (!bitmapHandle.valid()) return;
1472ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
14734387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck}
14744387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck
14754508218850faedea95371188da587b6734f5f3dasergeyvstatic jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
14764508218850faedea95371188da587b6734f5f3dasergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
14774508218850faedea95371188da587b6734f5f3dasergeyv    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
14784508218850faedea95371188da587b6734f5f3dasergeyv}
14794508218850faedea95371188da587b6734f5f3dasergeyv
14806e3658a63843096058ed444d073fbcd191fd7e1bsergeyvstatic jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
148181f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
148281f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
148381f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv            "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
148481f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
148581f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    SkBitmap src;
148681f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    hwuiBitmap.getSkBitmap(&src);
148781f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv
148881f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    SkBitmap result;
148981f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    HeapAllocator allocator;
149081f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) {
149181f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv        doThrowRE(env, "Could not copy a hardware bitmap.");
149281f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv        return NULL;
149381f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    }
1494656117bed2fc1937bcebd615898924ed57c48979sergeyv    return createBitmap(env, allocator.getStorageObjAndReset(), getPremulBitmapCreateFlags(false));
149581f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv}
149681f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv
14970a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyvstatic jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
14980a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
14990a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
15000a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    if (!bitmap.get()) {
15010a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv        ALOGW("failed to create hardware bitmap from graphic buffer");
15020a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv        return NULL;
15030a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    }
1504656117bed2fc1937bcebd615898924ed57c48979sergeyv    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
15050a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv}
15060a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv
15076e3658a63843096058ed444d073fbcd191fd7e1bsergeyvstatic jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
15086e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
15096e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
15106e3658a63843096058ed444d073fbcd191fd7e1bsergeyv            "Hardware config is only supported config in Bitmap_getGraphicBuffer");
15116e3658a63843096058ed444d073fbcd191fd7e1bsergeyv
15126e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
15136e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
15146e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    return createJavaGraphicBuffer(env, buffer);
15156e3658a63843096058ed444d073fbcd191fd7e1bsergeyv}
15166e3658a63843096058ed444d073fbcd191fd7e1bsergeyv
151732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
1518c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass make_globalref(JNIEnv* env, const char classname[])
1519c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1520c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jclass c = env->FindClass(classname);
1521c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(c);
1522c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return (jclass) env->NewGlobalRef(c);
1523c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
1524c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
1525c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1526c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv                                const char fieldname[], const char type[])
1527c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1528c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jfieldID id = env->GetFieldID(clazz, fieldname, type);
1529c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(id);
1530c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return id;
1531c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
153232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
153376f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gBitmapMethods[] = {
153432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
153532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_creator },
153632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
153732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_copy },
1538721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1539721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        (void*)Bitmap_copyAshmem },
1540a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1541a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson        (void*)Bitmap_copyAshmemConfig },
1542775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
154332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
15444508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
154532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
154632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_compress },
154732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
154832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
154932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
155032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
155157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
155257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
155357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
155432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
155532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
155632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreateFromParcel",
155732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
155832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_createFromParcel },
155932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
156032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_writeToParcel },
156132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
156232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_extractAlpha },
156332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
156457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
156557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
156657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
156757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
156832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
156932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsToBuffer },
157032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
157132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsFromBuffer },
157232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
15734387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
15744508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
157581f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    {   "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
15766e3658a63843096058ed444d073fbcd191fd7e1bsergeyv        (void*)Bitmap_copyPreserveInternalConfig },
15770a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
15786e3658a63843096058ed444d073fbcd191fd7e1bsergeyv        (void*) Bitmap_createHardwareBitmap },
15796e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
1580efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy        (void*) Bitmap_createGraphicBufferHandle },
1581efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
1582efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
158332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
158432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
158532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikint register_android_graphics_Bitmap(JNIEnv* env)
158632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik{
1587c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1588c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1589c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1590c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1591c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
1592ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1593ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                         NELEM(gBitmapMethods));
15949192d5e8d78b826a665ce048c007e6eaf0f5b003John Reck}
1595