Bitmap.cpp revision 5fd2a1cb2726afa7d40fe4750e9defd89c24ed37
1f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#define LOG_TAG "Bitmap"
2f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#include "Bitmap.h"
3f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkBitmap.h"
532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkPixelRef.h"
632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkImageEncoder.h"
757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III#include "SkImageInfo.h"
832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkColorPriv.h"
932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "GraphicsJNI.h"
1032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkDither.h"
1132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkUnPreMultiply.h"
1232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkStream.h"
1332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <binder/Parcel.h>
1532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_os_Parcel.h"
1632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_util_Binder.h"
1732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_nio_utils.h"
1832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "CreateJavaOutputStreamAdaptor.h"
19dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
20c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv#include <hwui/Bitmap.h>
214387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck#include <renderthread/RenderProxy.h>
2232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
23ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
24ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
2532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <jni.h>
2639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <memory>
2739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <string>
2832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
29a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#define DEBUG_PARCEL 0
308cee7c17119b204be88860feb812f2374d0de732Riley Andrews#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
31a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
32c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass   gBitmap_class;
33c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID gBitmap_nativePtr;
34c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_constructorMethodID;
35c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_reinitMethodID;
36c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_getAllocationByteCountMethodID;
37c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
38f29ed28c7b878ef28058bc730715d0d32445bc57John Recknamespace android {
39f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
40c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvclass BitmapWrapper {
41f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
42c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper(Bitmap* bitmap)
43c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        : mBitmap(bitmap) { }
44c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
45c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void freePixels() {
46c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mInfo = mBitmap->info();
47c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
48c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mAllocationSize = mBitmap->getAllocationByteCount();
49c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mRowBytes = mBitmap->rowBytes();
50c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mGenerationId = mBitmap->getGenerationID();
51c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap.reset();
52f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
53f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
54c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool valid() {
55fc9999505a36c66892d7ccce85187936105f4f36sergeyv        return mBitmap;
56f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
57f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
58aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    Bitmap& bitmap() {
59aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        assertValid();
60aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return *mBitmap;
61aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
62c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
63c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void assertValid() {
64c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
65c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
66c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
67c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void getSkBitmap(SkBitmap* outBitmap) {
68c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
69c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->getSkBitmap(outBitmap);
70c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
710781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
72c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool hasHardwareMipMap() {
73c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
74c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->hasHardwareMipMap();
75c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
76f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mHasHardwareMipMap;
77f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
78f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
79f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void setHasHardwareMipMap(bool hasMipMap) {
80c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
81c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setHasHardwareMipMap(hasMipMap);
82f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
83f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
84c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void setAlphaType(SkAlphaType alphaType) {
85c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
86c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setAlphaType(alphaType);
87f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
88f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
89c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    const SkImageInfo& info() {
90c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
91c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->info();
92c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
93c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mInfo;
94f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
95f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
96c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t getAllocationByteCount() const {
97c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
98c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getAllocationByteCount();
99c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
100c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mAllocationSize;
101f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
102f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
103c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t rowBytes() const {
104c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
105c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->rowBytes();
106c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
107c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mRowBytes;
108c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
109f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
110c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t getGenerationID() const {
111c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
112c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getGenerationID();
113c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
114c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mGenerationId;
115f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
116c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
117c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    ~BitmapWrapper() { }
118c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
119c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvprivate:
120c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> mBitmap;
121c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkImageInfo mInfo;
122c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool mHasHardwareMipMap;
123c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mAllocationSize;
124c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mRowBytes;
125c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t mGenerationId;
126f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
127f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
128f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// Convenience class that does not take a global ref on the pixels, relying
129f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// on the caller already having a local JNI ref
130f29ed28c7b878ef28058bc730715d0d32445bc57John Reckclass LocalScopedBitmap {
131f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
132c6baf563ba6aa207a48317c177b29f1d2b70cf3dChih-Hung Hsieh    explicit LocalScopedBitmap(jlong bitmapHandle)
133c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
134f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
135c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* operator->() {
136c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper;
137f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
138f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
139f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* pixels() {
140aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return mBitmapWrapper->bitmap().pixels();
141f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
142f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
143f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool valid() {
144c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper && mBitmapWrapper->valid();
145f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
146f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
147f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprivate:
148c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* mBitmapWrapper;
149f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
150f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
151c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvnamespace bitmap {
152c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
153c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
154c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
155c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
156c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // irrelevant. This just tests to ensure that the SkAlphaType is not
157c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // opposite of isPremultiplied.
158c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isPremultiplied) {
159c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
160c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    } else {
161c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
162c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
163c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
164c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
165c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
166c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        bool isPremultiplied)
167c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
168c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
169c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
170c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    assert_premultiplied(info, isPremultiplied);
171c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
172c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
173c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            info.width(), info.height(), isPremultiplied);
174c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
175c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
176c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvint getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
177c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
178c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
179c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
180c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
181c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvjobject createBitmap(JNIEnv* env, Bitmap* bitmap,
182c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
183c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int density) {
184c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
185c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
186c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
187c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
188c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    assert_premultiplied(bitmap->info(), isPremultiplied);
189c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
190c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
191c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
192c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
193c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
194c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (env->ExceptionCheck() != 0) {
195c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        ALOGE("*** Uncaught exception returned from Java call!\n");
196c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        env->ExceptionDescribe();
197c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
198c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return obj;
199c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
200c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
201c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
202c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap bitmap(bitmapHandle);
203c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->getSkBitmap(outBitmap);
204c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
205c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
206aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyvBitmap& toBitmap(JNIEnv* env, jobject bitmap) {
207c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env);
208c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(bitmap);
209c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
210c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
211c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
212c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return localBitmap->bitmap();
213c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
214c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
2155fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyvBitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
2165fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    SkASSERT(env);
2175fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
2185fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    return localBitmap->bitmap();
2195fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv}
2205fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv
221c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace bitmap
222c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
223c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace android
224c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
225c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android;
226c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android::bitmap;
227c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
22832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
22932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// Conversions to/from SkColor, for get/setPixels, and the create method, which
23032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// is basically like setPixels
23132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
23232054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
23332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              int x, int y);
23432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
23532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32(void* dst, const SkColor src[], int width,
23632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
23732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
23832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
23932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
24032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPreMultiplyColor(*src++);
24132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
24232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
24332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
24432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
24532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
24646d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    // Needed to thwart the unreachable code detection from clang.
24746d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
24846d8444631b4b1253a76bfcc78a29d26014d022fDan Albert
24932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // SkColor's ordering may be different from SkPMColor
25046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    if (sk_color_ne_zero) {
25132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        memcpy(dst, src, width * sizeof(SkColor));
25232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
25332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
25432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
25532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // order isn't same, repack each pixel manually
25632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
25732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
25832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
25932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
26032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   SkColorGetG(c), SkColorGetB(c));
26132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
26232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
26332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
26432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D565(void* dst, const SkColor src[], int width,
26532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           int x, int y) {
26632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    uint16_t* d = (uint16_t*)dst;
26732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
26832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_565_SCAN(y);
26932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
27032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
27132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
27232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                DITHER_VALUE(x));
27332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
27432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
27532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
27632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444(void* dst, const SkColor src[], int width,
27732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
27832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
27932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
28032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
28132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
28232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPreMultiplyColor(*src++);
28332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
28432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
28532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
28632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
28732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
28832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
28932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
29032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
29132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
29232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
29332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
29432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
29532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
29632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
29732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
29832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            SkColorGetG(c), SkColorGetB(c));
29932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
30032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
30132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
30232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
30332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
3046260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
3056260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    uint8_t* d = (uint8_t*)dst;
3066260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
3076260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    for (int stop = x + width; x < stop; x++) {
3086260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *d++ = SkColorGetA(*src++);
3096260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    }
3106260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
3116260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
31232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
31357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
31457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    switch (bitmap.colorType()) {
31557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kN32_SkColorType:
31657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
31757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kARGB_4444_SkColorType:
31857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
31957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    FromColor_D4444_Raw;
32057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kRGB_565_SkColorType:
32132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return FromColor_D565;
3226260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
3236260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return FromColor_DA8;
32432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
32532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
32632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
32732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
32832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
32932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
33032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikbool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
33157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
33232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkAutoLockPixels alp(dstBitmap);
33332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    void* dst = dstBitmap.getPixels();
33457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    FromColorProc proc = ChooseFromColorProc(dstBitmap);
33532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
33632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == dst || NULL == proc) {
33732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return false;
33832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
33932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
34032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const jint* array = env->GetIntArrayElements(srcColors, NULL);
34132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkColor* src = (const SkColor*)array + srcOffset;
34232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
34332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // reset to to actual choice from caller
34432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dst = dstBitmap.getAddr(x, y);
34532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now copy/convert each scanline
34632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < height; y++) {
34732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        proc(dst, src, width, x, y);
34832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        src += srcStride;
34932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        dst = (char*)dst + dstBitmap.rowBytes();
35032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
35132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
35232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dstBitmap.notifyPixelsChanged();
35332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
35432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
35532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 JNI_ABORT);
35632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return true;
35732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
35832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
35932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//////////////////// ToColor procs
36032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
36132054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
36232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            SkColorTable*);
36332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
36432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
36532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
36632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
36732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
36832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
36932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
37032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
37132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
37232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
37432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
37532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
37632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
37732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
37832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
37932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
38032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
38132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
38232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
38332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
38532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable*) {
38632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
38732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
38832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
38932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
39032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
39132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
39232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
39332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
39432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
39632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
39732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
39832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
39932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
40032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
40132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
40232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
40332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
40432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
40532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
40632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
40732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
40832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
40932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
41032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
41132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
41232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
41332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
41432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
41532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
41632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 SkColorTable*) {
41732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
41832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
41932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
42032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
42132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
42232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
42332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
42432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
42532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
42632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S565(SkColor dst[], const void* src, int width,
42732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                         SkColorTable*) {
42832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
42932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint16_t* s = (const uint16_t*)src;
43032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
43132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        uint16_t c = *s++;
43232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
43332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkPacked16ToB32(c));
43432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
43532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
43632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
43832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
43932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
44032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
44171487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
44232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
44332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
44432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
44532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
44632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
44832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
44932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
45032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
45171487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
45232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
45332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
45432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
45532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
45632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
45732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
45832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
45932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
46032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable* ctable) {
46132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
46232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
46371487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
46432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
46532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
46632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
46732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
46832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
46932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
47032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4716260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
4726260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    SkASSERT(width > 0);
4736260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    const uint8_t* s = (const uint8_t*)src;
4746260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    do {
4756260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        uint8_t c = *s++;
4766260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *dst++ = SkColorSetARGB(c, c, c, c);
4776260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    } while (--width != 0);
4786260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
4796260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
48032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
48157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic ToColorProc ChooseToColorProc(const SkBitmap& src) {
482b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    switch (src.colorType()) {
483b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kN32_SkColorType:
48457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
48557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
48657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Opaque;
48757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
48857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Alpha;
48957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
49057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Raw;
49157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
49257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
49357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
494b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kARGB_4444_SkColorType:
49557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
49657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
49757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Opaque;
49857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
49957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Alpha;
50057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
50157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Raw;
50257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
50357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
50457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
505b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kRGB_565_SkColorType:
50632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return ToColor_S565;
507b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kIndex_8_SkColorType:
50832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            if (src.getColorTable() == NULL) {
50932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                return NULL;
51032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            }
51157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
51257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
51357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Opaque;
51457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
51557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Alpha;
51657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
51757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Raw;
51857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
51957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
52057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
5216260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
5226260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return ToColor_SA8;
52332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
52432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
52532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
52632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
52732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
52832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
52932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
53032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
53132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
53232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic int getPremulBitmapCreateFlags(bool isMutable) {
533c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
534c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
53532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return flags;
53632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
53732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
53832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
53932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint offset, jint stride, jint width, jint height,
54032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint configHandle, jboolean isMutable) {
5411103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
54232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != jColors) {
54332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        size_t n = env->GetArrayLength(jColors);
54432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (n < SkAbs32(stride) * (size_t)height) {
54532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            doThrowAIOOBE(env);
54632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return NULL;
54732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
54832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
54932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
55032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // ARGB_4444 is a deprecated format, convert automatically to 8888
551b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kARGB_4444_SkColorType) {
552b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        colorType = kN32_SkColorType;
55332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
55432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
55532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkBitmap bitmap;
556253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
557253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            GraphicsJNI::defaultColorSpace()));
55832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
559c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
560f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!nativeBitmap) {
56132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
56232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
56332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
56432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (jColors != NULL) {
56532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        GraphicsJNI::SetPixels(env, jColors, offset, stride,
56657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                0, 0, width, height, bitmap);
56732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
56832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
569c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
57032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
57132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
57232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
57332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           jint dstConfigHandle, jboolean isMutable) {
574f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
575c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
5761103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
5774508218850faedea95371188da587b6734f5f3dasergeyv    SkBitmap result;
5784508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
57932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
580f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!src.copyTo(&result, dstCT, &allocator)) {
58132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
58232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
583c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
584c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
58532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
58632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
587c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
588721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    SkBitmap result;
589721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
590721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    AshmemPixelAllocator allocator(env);
591a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    if (!src.copyTo(&result, dstCT, &allocator)) {
592721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        return NULL;
593721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    }
594c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
595c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmap->setImmutable();
596c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return bitmap;
597a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
598a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
599a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
600a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
601c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
602a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = src.colorType();
603c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
604c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
605a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    return ret;
606a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
607a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
608a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
609a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
610c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
611a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
612c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
613c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
614721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    return ret;
615721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews}
616721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
617c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic void Bitmap_destruct(BitmapWrapper* bitmap) {
618c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    delete bitmap;
61932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
62032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
621775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
622775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
623775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler}
624775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
62532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
626f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
627f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->freePixels();
62832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
62932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
63032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
63132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
6324508218850faedea95371188da587b6734f5f3dasergeyv        jint width, jint height, jint configHandle, jboolean requestPremul) {
633f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
634c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->assertValid();
6351103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
63617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III
63717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    // ARGB_4444 is a deprecated format, convert automatically to 8888
63817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    if (colorType == kARGB_4444_SkColorType) {
63917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        colorType = kN32_SkColorType;
64017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
6414508218850faedea95371188da587b6734f5f3dasergeyv    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
6424508218850faedea95371188da587b6734f5f3dasergeyv    if (requestedSize > bitmap->getAllocationByteCount()) {
64332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // done in native as there's no way to get BytesPerPixel in Java
64432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowIAE(env, "Bitmap not large enough to support new configuration");
64532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
64632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
64717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    SkAlphaType alphaType;
648f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().colorType() != kRGB_565_SkColorType
649f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
65017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // If the original bitmap was set to opaque, keep that setting, unless it
65117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // was 565, which is required to be opaque.
65217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = kOpaque_SkAlphaType;
65317a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    } else {
65417a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // Otherwise respect the premultiplied request.
65517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
65617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
657aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
658253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            sk_sp<SkColorSpace>(bitmap->info().colorSpace())));
65932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
66032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
66132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// These must match the int values in Bitmap.java
66232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikenum JavaEncodeFormat {
66332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kJPEG_JavaEncodeFormat = 0,
66432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kPNG_JavaEncodeFormat = 1,
66532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kWEBP_JavaEncodeFormat = 2
66632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
66732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
66832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
66932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jint format, jint quality,
67032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jobject jstream, jbyteArray jstorage) {
671f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
672f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
67332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkImageEncoder::Type fm;
67432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
67532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    switch (format) {
67632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kJPEG_JavaEncodeFormat:
67732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kJPEG_Type;
67832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
67932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kPNG_JavaEncodeFormat:
68032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kPNG_Type;
68132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
68232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kWEBP_JavaEncodeFormat:
68332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kWEBP_Type;
68432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
68532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    default:
68632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
68732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
68832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
689f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap.valid()) {
690f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
691f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
69232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
693f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool success = false;
69432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
695f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
696f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!strm.get()) {
697f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
698f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
69932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
700f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkImageEncoder> encoder(SkImageEncoder::Create(fm));
701f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (encoder.get()) {
702f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkBitmap skbitmap;
703f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bitmap->getSkBitmap(&skbitmap);
704f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        success = encoder->encodeStream(strm.get(), skbitmap, quality);
70532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
70632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return success ? JNI_TRUE : JNI_FALSE;
70732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
70832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
70932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
710f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
711f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap skBitmap;
712f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->getSkBitmap(&skBitmap);
713f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    skBitmap.eraseColor(color);
71432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
71532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
71632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
717f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
71832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(bitmap->rowBytes());
71932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
72032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
72132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
722f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
723f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
72432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
72532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
72632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
727f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
728c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return static_cast<jint>(bitmap->getGenerationID());
72932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
73032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
73157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
732f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
733f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
73457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        return JNI_TRUE;
73557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
73657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    return JNI_FALSE;
73757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
73857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
73932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
740f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
741f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
74232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
74332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
74457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
74557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean hasAlpha, jboolean requestPremul) {
746f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
74757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    if (hasAlpha) {
7480781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(
749f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
75032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } else {
7510781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(kOpaque_SkAlphaType);
75257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
75357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
75457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
75557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
75657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean isPremul) {
757f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
758f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap->info().isOpaque()) {
75957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        if (isPremul) {
7600781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kPremul_SkAlphaType);
76157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        } else {
7620781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kUnpremul_SkAlphaType);
76357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        }
76432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
76532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
76632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
76732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
768f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
76932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
77032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
77132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
77232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
77332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jboolean hasMipMap) {
774f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
77532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    bitmap->setHasHardwareMipMap(hasMipMap);
77632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
77732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
77832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
77932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
78032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
78132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
78232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("-------- unparcel parcel is NULL\n");
78332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
78432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
78532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
78632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
78732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
788b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const bool        isMutable = p->readInt32() != 0;
789b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkColorType colorType = (SkColorType)p->readInt32();
790b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
791253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    const bool        isSRGB = p->readInt32() != 0;
792b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         width = p->readInt32();
793b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         height = p->readInt32();
794b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         rowBytes = p->readInt32();
795b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         density = p->readInt32();
796b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed
797b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (kN32_SkColorType != colorType &&
798b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kRGB_565_SkColorType != colorType &&
799b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kARGB_4444_SkColorType != colorType &&
800b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kIndex_8_SkColorType != colorType &&
801b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kAlpha_8_SkColorType != colorType) {
802b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
80332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
80432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
80532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
806ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
80732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
808253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
809253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy            isSRGB ? SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
810ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        return NULL;
811ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    }
81232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
81332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColorTable* ctable = NULL;
814b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kIndex_8_SkColorType) {
81532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int count = p->readInt32();
816ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        if (count < 0 || count > 256) {
817ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
818ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // inclusive.
819ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            return NULL;
820ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        }
82132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (count > 0) {
82232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            size_t size = count * sizeof(SkPMColor);
82332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
824ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            if (src == NULL) {
825ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III                return NULL;
826ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            }
82732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            ctable = new SkColorTable(src, count);
82832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
82932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
83032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
831a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Read the bitmap blob.
832a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap->getSize();
833a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::ReadableBlob blob;
834a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status = p->readBlob(size, &blob);
835a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
83632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkSafeUnref(ctable);
837a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not read bitmap blob.");
83832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
83932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
84032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
841a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Map the bitmap in place from the ashmem region if possible otherwise copy.
842c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap;
8438cee7c17119b204be88860feb812f2374d0de732Riley Andrews    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
844a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
845a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
846a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "(fds %s)",
847a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                isMutable ? "mutable" : "immutable",
848a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                blob.isMutable() ? "mutable" : "immutable",
849a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
850a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
851a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Dup the file descriptor so we can keep a reference to it after the Parcel
852a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // is disposed.
853a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        int dupFd = dup(blob.fd());
854a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (dupFd < 0) {
855211abad3b92b70dd094949c79f67e686c940fa0cErik Wolsheimer            ALOGE("Error allocating dup fd. Error:%d", errno);
856a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
857a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            SkSafeUnref(ctable);
858a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate dup blob fd.");
859a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
86039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
861a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
862a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Map the pixels in place and take ownership of the ashmem region.
863c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
864c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
865a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
866a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
867a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            close(dupFd);
868a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
869a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate ashmem pixel ref.");
870a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
87139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
872a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
873a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Clear the blob handle, don't release it.
874a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.clear();
875a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
876a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
877a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (blob.fd() >= 0) {
878a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
879a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "from immutable blob (fds %s)",
880a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
881a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        } else {
882a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
883a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "(fds %s)",
884a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    blob.isMutable() ? "mutable" : "immutable",
885a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
88639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
887a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
888a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
889a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Copy the pixels into a new buffer.
890c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
891a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
892a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
893a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
894a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate java pixel ref.");
895a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
89639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
897a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->lockPixels();
898a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(bitmap->getPixels(), blob.data(), size);
899a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->unlockPixels();
900a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
901a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Release the blob handle.
902a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.release();
90339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
904a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
905c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(),
906a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
907a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown}
90839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
90932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
91032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jlong bitmapHandle,
91132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jboolean isMutable, jint density,
91232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jobject parcel) {
91332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
91432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("------- writeToParcel null parcel\n");
91532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
91632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
91732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
91832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
919f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
92039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
921c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
922c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmapWrapper->getSkBitmap(&bitmap);
92332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
924253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
925253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    bool isSRGB = bitmap.colorSpace() == sRGB.get();
926253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy
92732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(isMutable);
928f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.colorType());
929f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.alphaType());
930253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
931f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.width());
932f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.height());
933f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.rowBytes());
93432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(density);
93532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
936f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap.colorType() == kIndex_8_SkColorType) {
93766ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        // The bitmap needs to be locked to access its color table.
93866ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        SkAutoLockPixels alp(bitmap);
939f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ctable = bitmap.getColorTable();
94032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ctable != NULL) {
94132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            int count = ctable->count();
94232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(count);
94332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
94471487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed                   ctable->readColors(), count * sizeof(SkPMColor));
94532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        } else {
94632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(0);   // indicate no ctable
94732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
94832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
94932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
950a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Transfer the underlying ashmem region if we have one and it's immutable.
951a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status;
952aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    int fd = bitmapWrapper->bitmap().getAshmemFd();
953a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (fd >= 0 && !isMutable && p->allowFds()) {
954a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
955a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
956a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "immutable blob (fds %s)",
957a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
958a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
959a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
960a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        status = p->writeDupImmutableBlobFileDescriptor(fd);
961a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (status) {
962a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not write bitmap blob file descriptor.");
96339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews            return JNI_FALSE;
96439d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
965a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_TRUE;
966a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
96732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
968a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Copy the bitmap to a new blob.
969a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bool mutableCopy = isMutable;
970a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
971a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
972a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            isMutable ? "mutable" : "immutable",
973a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            mutableCopy ? "mutable" : "immutable",
974a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            p->allowFds() ? "allowed" : "forbidden");
975a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
976a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
977a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap.getSize();
978a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::WritableBlob blob;
979a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    status = p->writeBlob(size, mutableCopy, &blob);
980a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
981a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not copy bitmap to parcel blob.");
982a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_FALSE;
98339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
984a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
985a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.lockPixels();
986a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    const void* pSrc =  bitmap.getPixels();
987a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (pSrc == NULL) {
988a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memset(blob.data(), 0, size);
989a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
990a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(blob.data(), pSrc, size);
991a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
992a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.unlockPixels();
993a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
994a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    blob.release();
99532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
99632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
99732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
99832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
99932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jlong srcHandle, jlong paintHandle,
100032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jintArray offsetXY) {
1001f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
1002c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
10036ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
100432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkIPoint  offset;
1005f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap dst;
10064508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
100732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1008f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    src.extractAlpha(&dst, paint, &allocator, &offset);
100932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // If Skia can't allocate pixels for destination bitmap, it resets
101032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // it, that is set its pixels buffer to NULL, and zero width and height.
1011f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
101232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowOOME(env, "failed to allocate pixels for alpha");
101332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
101432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
101532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
101632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int* array = env->GetIntArrayElements(offsetXY, NULL);
101732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[0] = offset.fX;
101832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[1] = offset.fY;
101932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        env->ReleaseIntArrayElements(offsetXY, array, 0);
102032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
102132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1022c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, allocator.getStorageObjAndReset(),
1023f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(true));
102432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
102532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
102632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
102732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
102832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
102957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y) {
1030f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1031c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1032f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
103332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1034f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
103532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
103632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
103732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1038f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
103932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
104032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
104132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
104232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
104332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor dst[1];
1044f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(dst, src, 1, bitmap.getColorTable());
104532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(dst[0]);
104632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
104732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
104832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
104932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
105057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1051f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1052c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1053f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
105432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1055f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
105632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
105732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
105832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1059f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
106032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
106132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
106232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
106332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1064f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkColorTable* ctable = bitmap.getColorTable();
106532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
106632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor* d = (SkColor*)dst + offset;
106732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    while (--height >= 0) {
106832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        proc(d, src, width, ctable);
106932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        d += stride;
1070f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        src = (void*)((const char*)src + bitmap.rowBytes());
107132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
107232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(pixelArray, dst, 0);
107332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
107432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
107532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
107632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
107732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
107857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint colorHandle) {
1079f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1080c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
108132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor color = static_cast<SkColor>(colorHandle);
1082f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1083f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bitmap.getPixels()) {
108432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
108532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
108632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1087f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    FromColorProc proc = ChooseFromColorProc(bitmap);
108832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
108932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
109032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
109132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1092f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1093f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap.notifyPixelsChanged();
109432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
109532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
109632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
109732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
109857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1099f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1100c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
110132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1102f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            x, y, width, height, bitmap);
110332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
110432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
110532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
110632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                      jlong bitmapHandle, jobject jbuffer) {
1107f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1108c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1109f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1110f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getPixels();
111132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
111232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != src) {
111332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
111432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
111532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1116f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(abp.pointer(), src, bitmap.getSize());
111732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
111832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
111932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
112032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
112132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                        jlong bitmapHandle, jobject jbuffer) {
1122f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1123c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1124f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1125f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* dst = bitmap.getPixels();
112632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
112732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != dst) {
112832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
112932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1130f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(dst, abp.pointer(), bitmap.getSize());
1131f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bitmap.notifyPixelsChanged();
113232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
113332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
113432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
113532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
113632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jlong bm1Handle) {
1137f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm0;
1138f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm1;
1139c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bm0Handle)->getSkBitmap(&bm0);
1140c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bm1Handle)->getSkBitmap(&bm1);
1141f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bm0.width() != bm1.width() ||
1142f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bm0.height() != bm1.height() ||
1143253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy        bm0.colorType() != bm1.colorType() ||
1144253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy        bm0.alphaType() != bm1.alphaType() ||
1145253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy        bm0.colorSpace() != bm1.colorSpace()) {
114632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
114732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
114832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1149f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp0(bm0);
1150f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp1(bm1);
115132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
115232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // if we can't load the pixels, return false
1153f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
115432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
115532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
115632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1157f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bm0.colorType() == kIndex_8_SkColorType) {
1158f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct0 = bm0.getColorTable();
1159f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct1 = bm1.getColorTable();
116032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (NULL == ct0 || NULL == ct1) {
116132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
116232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
116332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ct0->count() != ct1->count()) {
116432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
116532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
116632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
116732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        const size_t size = ct0->count() * sizeof(SkPMColor);
116871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
116932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
117032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
117132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
117232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
117332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now compare each scanline. We can't do the entire buffer at once,
117432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // since we don't care about the pixel values that might extend beyond
117532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // the width (since the scanline might be larger than the logical width)
1176f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const int h = bm0.height();
1177f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const size_t size = bm0.width() * bm0.bytesPerPixel();
117832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < h; y++) {
117953001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
118053001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
118153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
118253001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
118353001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // to warn user those 2 unrecognized config bitmaps may be different.
1184f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm0Addr = bm0.getAddr(0, y);
1185f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm1Addr = bm1.getAddr(0, y);
118653001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
118753001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if(bm0Addr == NULL || bm1Addr == NULL) {
118853001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen            return JNI_FALSE;
118953001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        }
119053001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
119153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
119232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
119332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
119432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
119532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
119632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
119732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
11981158b6d4ee34707515d5af59a13e4999ba53563eRomain Guystatic jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
11991158b6d4ee34707515d5af59a13e4999ba53563eRomain Guy    LocalScopedBitmap bitmap(bitmapHandle);
1200aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    SkPixelRef& pixelRef = bitmap->bitmap();
1201aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    pixelRef.ref();
1202aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    return reinterpret_cast<jlong>(&pixelRef);
12031158b6d4ee34707515d5af59a13e4999ba53563eRomain Guy}
12041158b6d4ee34707515d5af59a13e4999ba53563eRomain Guy
12054387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reckstatic void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
12064387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    LocalScopedBitmap bitmapHandle(bitmapPtr);
12074387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    if (!bitmapHandle.valid()) return;
12084387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    SkBitmap bitmap;
12094387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    bitmapHandle->getSkBitmap(&bitmap);
12104387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmap);
12114387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck}
12124387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck
12134508218850faedea95371188da587b6734f5f3dasergeyvstatic jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
12144508218850faedea95371188da587b6734f5f3dasergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
12154508218850faedea95371188da587b6734f5f3dasergeyv    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
12164508218850faedea95371188da587b6734f5f3dasergeyv}
12174508218850faedea95371188da587b6734f5f3dasergeyv
121832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
1219c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass make_globalref(JNIEnv* env, const char classname[])
1220c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1221c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jclass c = env->FindClass(classname);
1222c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(c);
1223c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return (jclass) env->NewGlobalRef(c);
1224c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
1225c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
1226c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1227c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv                                const char fieldname[], const char type[])
1228c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1229c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jfieldID id = env->GetFieldID(clazz, fieldname, type);
1230c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(id);
1231c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return id;
1232c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
123332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
123476f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gBitmapMethods[] = {
123532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
123632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_creator },
123732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
123832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_copy },
1239721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1240721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        (void*)Bitmap_copyAshmem },
1241a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1242a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson        (void*)Bitmap_copyAshmemConfig },
1243775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
124432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
12454508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
124632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
124732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_compress },
124832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
124932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
125032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
125132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
125257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
125357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
125457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
125532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
125632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
125732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreateFromParcel",
125832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
125932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_createFromParcel },
126032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
126132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_writeToParcel },
126232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
126332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_extractAlpha },
126432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
126557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
126657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
126757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
126857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
126932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
127032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsToBuffer },
127132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
127232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsFromBuffer },
127332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
12741158b6d4ee34707515d5af59a13e4999ba53563eRomain Guy    {   "nativeRefPixelRef",        "(J)J", (void*)Bitmap_refPixelRef },
12754387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
12764508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
127732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
127832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
127932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikint register_android_graphics_Bitmap(JNIEnv* env)
128032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik{
1281c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1282c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1283c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1284c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1285c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
1286ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1287ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                         NELEM(gBitmapMethods));
1288c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}