Bitmap.cpp revision 15a108550e3d74b406927d85c8e69018761adf49
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"
89505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkColor.h"
932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkColorPriv.h"
109505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkHalf.h"
119505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkPM4f.h"
129505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkPM4fPriv.h"
1332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "GraphicsJNI.h"
1432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkDither.h"
1532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkUnPreMultiply.h"
1632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkStream.h"
1732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <binder/Parcel.h>
1932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_os_Parcel.h"
2032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_util_Binder.h"
2132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_nio_utils.h"
2232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "CreateJavaOutputStreamAdaptor.h"
23dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
24c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv#include <hwui/Bitmap.h>
254387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck#include <renderthread/RenderProxy.h>
2632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
27ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
28ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
2932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <jni.h>
3039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <memory>
3139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <string>
3232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
33a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#define DEBUG_PARCEL 0
348cee7c17119b204be88860feb812f2374d0de732Riley Andrews#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
35a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
36c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass   gBitmap_class;
37c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID gBitmap_nativePtr;
38c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_constructorMethodID;
39c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_reinitMethodID;
40c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_getAllocationByteCountMethodID;
41c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
42f29ed28c7b878ef28058bc730715d0d32445bc57John Recknamespace android {
43f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
44c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvclass BitmapWrapper {
45f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
46c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper(Bitmap* bitmap)
47c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        : mBitmap(bitmap) { }
48c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
49c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void freePixels() {
50c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mInfo = mBitmap->info();
51c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
52c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mAllocationSize = mBitmap->getAllocationByteCount();
53c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mRowBytes = mBitmap->rowBytes();
54c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mGenerationId = mBitmap->getGenerationID();
5515a108550e3d74b406927d85c8e69018761adf49sergeyv        mIsHardware = mBitmap->isHardware();
56c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap.reset();
57f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
58f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
59c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool valid() {
60fc9999505a36c66892d7ccce85187936105f4f36sergeyv        return mBitmap;
61f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
62f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
63aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    Bitmap& bitmap() {
64aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        assertValid();
65aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return *mBitmap;
66aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
67c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
68c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void assertValid() {
69c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
70c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
71c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
72c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void getSkBitmap(SkBitmap* outBitmap) {
73c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
74c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->getSkBitmap(outBitmap);
75c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
760781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
77c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool hasHardwareMipMap() {
78c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
79c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->hasHardwareMipMap();
80c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
81f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mHasHardwareMipMap;
82f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
83f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
84f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void setHasHardwareMipMap(bool hasMipMap) {
85c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
86c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setHasHardwareMipMap(hasMipMap);
87f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
88f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
89c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void setAlphaType(SkAlphaType alphaType) {
90c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
91c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setAlphaType(alphaType);
92f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
93f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
94c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    const SkImageInfo& info() {
95c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
96c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->info();
97c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
98c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mInfo;
99f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
100f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
101c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t getAllocationByteCount() const {
102c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
103c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getAllocationByteCount();
104c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
105c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mAllocationSize;
106f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
107f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
108c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t rowBytes() const {
109c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
110c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->rowBytes();
111c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
112c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mRowBytes;
113c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
114f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
115c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t getGenerationID() const {
116c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
117c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getGenerationID();
118c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
119c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mGenerationId;
120f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
121c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
12215a108550e3d74b406927d85c8e69018761adf49sergeyv    bool isHardware() {
12315a108550e3d74b406927d85c8e69018761adf49sergeyv        if (mBitmap) {
12415a108550e3d74b406927d85c8e69018761adf49sergeyv            return mBitmap->isHardware();
12515a108550e3d74b406927d85c8e69018761adf49sergeyv        }
12615a108550e3d74b406927d85c8e69018761adf49sergeyv        return mIsHardware;
12715a108550e3d74b406927d85c8e69018761adf49sergeyv    }
12815a108550e3d74b406927d85c8e69018761adf49sergeyv
129c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    ~BitmapWrapper() { }
130c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
131c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvprivate:
132c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> mBitmap;
133c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkImageInfo mInfo;
134c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool mHasHardwareMipMap;
135c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mAllocationSize;
136c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mRowBytes;
137c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t mGenerationId;
13815a108550e3d74b406927d85c8e69018761adf49sergeyv    bool mIsHardware;
139f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
140f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
141f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// Convenience class that does not take a global ref on the pixels, relying
142f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// on the caller already having a local JNI ref
143f29ed28c7b878ef28058bc730715d0d32445bc57John Reckclass LocalScopedBitmap {
144f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
145c6baf563ba6aa207a48317c177b29f1d2b70cf3dChih-Hung Hsieh    explicit LocalScopedBitmap(jlong bitmapHandle)
146c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
147f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
148c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* operator->() {
149c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper;
150f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
151f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
152f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* pixels() {
153aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return mBitmapWrapper->bitmap().pixels();
154f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
155f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
156f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool valid() {
157c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper && mBitmapWrapper->valid();
158f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
159f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
160f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprivate:
161c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* mBitmapWrapper;
162f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
163f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
164c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvnamespace bitmap {
165c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
166c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
167c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
168c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
169c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // irrelevant. This just tests to ensure that the SkAlphaType is not
170c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // opposite of isPremultiplied.
171c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isPremultiplied) {
172c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
173c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    } else {
174c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
175c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
176c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
177c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
178c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
179c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        bool isPremultiplied)
180c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
181c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
182c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
183c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    assert_premultiplied(info, isPremultiplied);
184c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
185c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
186c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            info.width(), info.height(), isPremultiplied);
187c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
188c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
189c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvint getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
190c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
191c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
192c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
193c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
194c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvjobject createBitmap(JNIEnv* env, Bitmap* bitmap,
195c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
196c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int density) {
197c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
198c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
199c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
200c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
201c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    assert_premultiplied(bitmap->info(), isPremultiplied);
202c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
203c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
204c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
205c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
206c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
207c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (env->ExceptionCheck() != 0) {
208c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        ALOGE("*** Uncaught exception returned from Java call!\n");
209c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        env->ExceptionDescribe();
210c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
211c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return obj;
212c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
213c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
214c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
215c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap bitmap(bitmapHandle);
216c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->getSkBitmap(outBitmap);
217c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
218c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
219aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyvBitmap& toBitmap(JNIEnv* env, jobject bitmap) {
220c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env);
221c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(bitmap);
222c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
223c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
224c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
225c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return localBitmap->bitmap();
226c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
227c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
2285fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyvBitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
2295fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    SkASSERT(env);
2305fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
2315fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    return localBitmap->bitmap();
2325fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv}
2335fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv
234c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace bitmap
235c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
236c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace android
237c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
238c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android;
239c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android::bitmap;
240c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
24132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
24232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// Conversions to/from SkColor, for get/setPixels, and the create method, which
24332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// is basically like setPixels
24432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
24532054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
24632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              int x, int y);
24732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
2489505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void FromColor_F16(void* dst, const SkColor src[], int width,
2499505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                          int, int) {
2509505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* d = (uint64_t*)dst;
2519505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
2529505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    for (int i = 0; i < width; i++) {
2539505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
2549505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
2559505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
2569505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
2579505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
2589505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                          int, int) {
2599505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* d = (uint64_t*)dst;
2609505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
2619505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    for (int i = 0; i < width; i++) {
2629505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        const float* color = SkColor4f::FromColor(*src++).vec();
2639505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
2649505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        for (int i = 0; i < 4; ++i) {
2659505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            scratch[i] = SkFloatToHalf(color[i]);
2669505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        }
2679505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
2689505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
2699505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
27032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32(void* dst, const SkColor src[], int width,
27132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
27232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
27332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
27432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
27532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPreMultiplyColor(*src++);
27632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
27732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
27832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
27932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
28032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
28146d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    // Needed to thwart the unreachable code detection from clang.
28246d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
28346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert
28432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // SkColor's ordering may be different from SkPMColor
28546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    if (sk_color_ne_zero) {
28632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        memcpy(dst, src, width * sizeof(SkColor));
28732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
28832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
28932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
29032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // order isn't same, repack each pixel manually
29132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
29232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
29332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
29432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
29532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   SkColorGetG(c), SkColorGetB(c));
29632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
29732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
29832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
29932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D565(void* dst, const SkColor src[], int width,
30032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           int x, int y) {
30132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    uint16_t* d = (uint16_t*)dst;
30232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
30332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_565_SCAN(y);
30432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
30532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
30632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
30732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                DITHER_VALUE(x));
30832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
30932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
31032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
31132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444(void* dst, const SkColor src[], int width,
31232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
31332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
31432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
31532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
31632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
31732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPreMultiplyColor(*src++);
31832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
31932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
32032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
32132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
32232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
32332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
32432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
32532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
32632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
32732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
32832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
32932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
33032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
33132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
33232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
33332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            SkColorGetG(c), SkColorGetB(c));
33432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
33532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
33632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
33732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
33832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
3396260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
3406260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    uint8_t* d = (uint8_t*)dst;
3416260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
3426260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    for (int stop = x + width; x < stop; x++) {
3436260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *d++ = SkColorGetA(*src++);
3446260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    }
3456260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
3466260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
34732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
34857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
34957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    switch (bitmap.colorType()) {
35057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kN32_SkColorType:
35157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
35257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kARGB_4444_SkColorType:
35357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
35457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    FromColor_D4444_Raw;
35557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kRGB_565_SkColorType:
35632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return FromColor_D565;
3576260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
3586260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return FromColor_DA8;
3599505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        case kRGBA_F16_SkColorType:
3609505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
36132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
36232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
36332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
36432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
36532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
36632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
36732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikbool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
36857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
36932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkAutoLockPixels alp(dstBitmap);
37032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    void* dst = dstBitmap.getPixels();
37157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    FromColorProc proc = ChooseFromColorProc(dstBitmap);
37232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == dst || NULL == proc) {
37432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return false;
37532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
37632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const jint* array = env->GetIntArrayElements(srcColors, NULL);
37832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkColor* src = (const SkColor*)array + srcOffset;
37932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // reset to to actual choice from caller
38132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dst = dstBitmap.getAddr(x, y);
38232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now copy/convert each scanline
38332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < height; y++) {
38432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        proc(dst, src, width, x, y);
38532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        src += srcStride;
38632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        dst = (char*)dst + dstBitmap.rowBytes();
38732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
38832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dstBitmap.notifyPixelsChanged();
39032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
3919505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
39232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return true;
39332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
39432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//////////////////// ToColor procs
39632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39732054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
39832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            SkColorTable*);
39932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4009505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
4019505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                              SkColorTable*) {
4029505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    SkASSERT(width > 0);
4039505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* s = (uint64_t*)src;
4049505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    do {
4059505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
4069505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    } while (--width != 0);
4079505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
4089505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
4099505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
4109505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                            SkColorTable*) {
4119505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    SkASSERT(width > 0);
4129505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* s = (uint64_t*)src;
4139505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    do {
4149505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
4159505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    } while (--width != 0);
4169505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
4179505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
41832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
41932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
42032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
42132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
42232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
42332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
42432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
42532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
42632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
42732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
42832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
42932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
43032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
43132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
43232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
43332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
43432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
43532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
43632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
43732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
43932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable*) {
44032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
44132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
44232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
44332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
44432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
44532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
44632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
44732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
44832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
45032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
45132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
45232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
45332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
45432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
45532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
45632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
45732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
45832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
45932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
46032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
46132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
46232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
46332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
46432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
46532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
46632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
46732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
46832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
46932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
47032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 SkColorTable*) {
47132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
47232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
47332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
47432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
47532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
47632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
47732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
47832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
47932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
48032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S565(SkColor dst[], const void* src, int width,
48132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                         SkColorTable*) {
48232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
48332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint16_t* s = (const uint16_t*)src;
48432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
48532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        uint16_t c = *s++;
48632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
48732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkPacked16ToB32(c));
48832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
48932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
49032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
49132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
49232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
49332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
49432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
49571487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
49632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
49732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
49832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
49932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
50032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
50132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
50232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
50332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
50432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
50571487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
50632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
50732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
50832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
50932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
51032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
51132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
51232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
51332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
51432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable* ctable) {
51532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
51632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
51771487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
51832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
51932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
52032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
52132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
52232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
52332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
52432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
5256260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
5266260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    SkASSERT(width > 0);
5276260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    const uint8_t* s = (const uint8_t*)src;
5286260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    do {
5296260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        uint8_t c = *s++;
5306260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *dst++ = SkColorSetARGB(c, c, c, c);
5316260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    } while (--width != 0);
5326260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
5336260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
53432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
53557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic ToColorProc ChooseToColorProc(const SkBitmap& src) {
536b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    switch (src.colorType()) {
537b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kN32_SkColorType:
53857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
53957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
54057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Opaque;
54157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
54257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Alpha;
54357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
54457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Raw;
54557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
54657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
54757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
548b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kARGB_4444_SkColorType:
54957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
55057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
55157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Opaque;
55257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
55357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Alpha;
55457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
55557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Raw;
55657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
55757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
55857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
559b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kRGB_565_SkColorType:
56032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return ToColor_S565;
561b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kIndex_8_SkColorType:
56232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            if (src.getColorTable() == NULL) {
56332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                return NULL;
56432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            }
56557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
56657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
56757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Opaque;
56857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
56957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Alpha;
57057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
57157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Raw;
57257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
57357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
57457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
5756260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
5766260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return ToColor_SA8;
5779505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        case kRGBA_F16_SkColorType:
5789505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            switch (src.alphaType()) {
5799505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kOpaque_SkAlphaType:
5809505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Raw;
5819505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kPremul_SkAlphaType:
5829505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Alpha;
5839505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kUnpremul_SkAlphaType:
5849505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Raw;
5859505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                default:
5869505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return NULL;
5879505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            }
58832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
58932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
59032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
59132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
59232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
59332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
59432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
59532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
59632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
59732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic int getPremulBitmapCreateFlags(bool isMutable) {
598c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
599c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
60032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return flags;
60132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
60232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
60332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
60432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint offset, jint stride, jint width, jint height,
60532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint configHandle, jboolean isMutable) {
6061103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
60732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != jColors) {
60832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        size_t n = env->GetArrayLength(jColors);
60932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (n < SkAbs32(stride) * (size_t)height) {
61032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            doThrowAIOOBE(env);
61132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return NULL;
61232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
61332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
61432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
61532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // ARGB_4444 is a deprecated format, convert automatically to 8888
616b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kARGB_4444_SkColorType) {
617b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        colorType = kN32_SkColorType;
61832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
61932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
62032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkBitmap bitmap;
621253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
6229505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            GraphicsJNI::colorSpaceForType(colorType)));
62332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
624c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
625f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!nativeBitmap) {
62632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
62732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
62832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
62932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (jColors != NULL) {
6309505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
63132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
63232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
633c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
63432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
63532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
63632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
63732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           jint dstConfigHandle, jboolean isMutable) {
638f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
639c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
64005126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv    if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
64105126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
64205126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        if (!bitmap.get()) {
64305126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv            return NULL;
64405126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        }
64505126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        return createBitmap(env, bitmap.release(), kBitmapCreateFlag_None);
64605126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv    }
64705126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv
6481103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
6494508218850faedea95371188da587b6734f5f3dasergeyv    SkBitmap result;
6504508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
65132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
652f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!src.copyTo(&result, dstCT, &allocator)) {
65332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
65432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
655c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
656c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
65732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
65832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
659c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
660721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    SkBitmap result;
661721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
662721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    AshmemPixelAllocator allocator(env);
663a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    if (!src.copyTo(&result, dstCT, &allocator)) {
664721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        return NULL;
665721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    }
666c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
667c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmap->setImmutable();
668c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return bitmap;
669a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
670a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
671a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
672a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
673c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
674a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = src.colorType();
675c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
676c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
677a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    return ret;
678a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
679a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
680a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
681a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
682c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
683a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
684c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
685c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
686721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    return ret;
687721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews}
688721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
689c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic void Bitmap_destruct(BitmapWrapper* bitmap) {
690c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    delete bitmap;
69132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
69232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
693775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
694775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
695775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler}
696775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
69732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
698f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
699f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->freePixels();
70032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
70132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
70232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
70332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
7044508218850faedea95371188da587b6734f5f3dasergeyv        jint width, jint height, jint configHandle, jboolean requestPremul) {
705f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
706c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->assertValid();
7071103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
70817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III
70917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    // ARGB_4444 is a deprecated format, convert automatically to 8888
71017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    if (colorType == kARGB_4444_SkColorType) {
71117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        colorType = kN32_SkColorType;
71217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
7134508218850faedea95371188da587b6734f5f3dasergeyv    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
7144508218850faedea95371188da587b6734f5f3dasergeyv    if (requestedSize > bitmap->getAllocationByteCount()) {
71532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // done in native as there's no way to get BytesPerPixel in Java
71632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowIAE(env, "Bitmap not large enough to support new configuration");
71732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
71832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
71917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    SkAlphaType alphaType;
720f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().colorType() != kRGB_565_SkColorType
721f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
72217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // If the original bitmap was set to opaque, keep that setting, unless it
72317a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // was 565, which is required to be opaque.
72417a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = kOpaque_SkAlphaType;
72517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    } else {
72617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // Otherwise respect the premultiplied request.
72717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
72817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
729aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
7307d5219fb505ff1b178910cda25a40154e7d4d09asergeyv            sk_ref_sp(bitmap->info().colorSpace())));
73132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
73232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
73332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// These must match the int values in Bitmap.java
73432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikenum JavaEncodeFormat {
73532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kJPEG_JavaEncodeFormat = 0,
73632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kPNG_JavaEncodeFormat = 1,
73732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kWEBP_JavaEncodeFormat = 2
73832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
73932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
74032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
74132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jint format, jint quality,
74232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jobject jstream, jbyteArray jstorage) {
74310219fb261606fcc71c607167b28295b4578a10dHal Canary    SkEncodedImageFormat fm;
74432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    switch (format) {
74532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kJPEG_JavaEncodeFormat:
74610219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kJPEG;
74732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
74832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kPNG_JavaEncodeFormat:
74910219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kPNG;
75032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
75132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kWEBP_JavaEncodeFormat:
75210219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kWEBP;
75332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
75432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    default:
75532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
75632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
75732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
75810219fb261606fcc71c607167b28295b4578a10dHal Canary    LocalScopedBitmap bitmap(bitmapHandle);
759f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap.valid()) {
760f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
761f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
76232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
763f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
764f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!strm.get()) {
765f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
766f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
76732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
76810219fb261606fcc71c607167b28295b4578a10dHal Canary    SkBitmap skbitmap;
76910219fb261606fcc71c607167b28295b4578a10dHal Canary    bitmap->getSkBitmap(&skbitmap);
77010219fb261606fcc71c607167b28295b4578a10dHal Canary    return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
77132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
77232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
77332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
774f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
775f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap skBitmap;
776f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->getSkBitmap(&skBitmap);
777f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    skBitmap.eraseColor(color);
77832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
77932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
78032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
781f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
78232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(bitmap->rowBytes());
78332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
78432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
78532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
786f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
78715a108550e3d74b406927d85c8e69018761adf49sergeyv    if (bitmap->isHardware()) {
78819b4b019169424d62bf3edc40b9560984206cf80sergeyv        return GraphicsJNI::hardwareLegacyBitmapConfig();
78919b4b019169424d62bf3edc40b9560984206cf80sergeyv    }
790f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
79132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
79232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
79332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
794f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
795c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return static_cast<jint>(bitmap->getGenerationID());
79632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
79732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
79857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
799f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
800f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
80157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        return JNI_TRUE;
80257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
80357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    return JNI_FALSE;
80457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
80557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
80632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
807f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
808f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
80932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
81032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
81157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
81257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean hasAlpha, jboolean requestPremul) {
813f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
81457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    if (hasAlpha) {
8150781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(
816f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
81732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } else {
8180781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(kOpaque_SkAlphaType);
81957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
82057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
82157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
82257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
82357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean isPremul) {
824f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
825f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap->info().isOpaque()) {
82657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        if (isPremul) {
8270781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kPremul_SkAlphaType);
82857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        } else {
8290781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kUnpremul_SkAlphaType);
83057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        }
83132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
83232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
83332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
83432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
835f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
83632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
83732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
83832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
83932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
84032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jboolean hasMipMap) {
841f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
84232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    bitmap->setHasHardwareMipMap(hasMipMap);
84332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
84432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
84532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
84632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
84732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
84832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
84932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("-------- unparcel parcel is NULL\n");
85032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
85132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
85232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
85332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
85432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
855b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const bool        isMutable = p->readInt32() != 0;
856b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkColorType colorType = (SkColorType)p->readInt32();
857b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
858253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    const bool        isSRGB = p->readInt32() != 0;
859b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         width = p->readInt32();
860b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         height = p->readInt32();
861b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         rowBytes = p->readInt32();
862b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         density = p->readInt32();
863b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed
864b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (kN32_SkColorType != colorType &&
8659505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            kRGBA_F16_SkColorType != colorType &&
866b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kRGB_565_SkColorType != colorType &&
867b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kARGB_4444_SkColorType != colorType &&
868b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kIndex_8_SkColorType != colorType &&
869b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kAlpha_8_SkColorType != colorType) {
870b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
87132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
87232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
87332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
874ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
87532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
8769505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    sk_sp<SkColorSpace> colorSpace;
8779505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    if (kRGBA_F16_SkColorType == colorType) {
8789505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
8799505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    } else {
8809505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        colorSpace = isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr;
8819505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
8829505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
8839505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
8849505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            rowBytes)) {
885ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        return NULL;
886ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    }
88732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
88832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColorTable* ctable = NULL;
889b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kIndex_8_SkColorType) {
89032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int count = p->readInt32();
891ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        if (count < 0 || count > 256) {
892ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
893ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // inclusive.
894ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            return NULL;
895ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        }
89632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (count > 0) {
89732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            size_t size = count * sizeof(SkPMColor);
89832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
899ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            if (src == NULL) {
900ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III                return NULL;
901ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            }
90232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            ctable = new SkColorTable(src, count);
90332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
90432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
90532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
906a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Read the bitmap blob.
907a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap->getSize();
908a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::ReadableBlob blob;
909a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status = p->readBlob(size, &blob);
910a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
91132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkSafeUnref(ctable);
912a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not read bitmap blob.");
91332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
91432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
91532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
916a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Map the bitmap in place from the ashmem region if possible otherwise copy.
917c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap;
9188cee7c17119b204be88860feb812f2374d0de732Riley Andrews    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
919a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
920a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
921a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "(fds %s)",
922a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                isMutable ? "mutable" : "immutable",
923a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                blob.isMutable() ? "mutable" : "immutable",
924a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
925a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
926a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Dup the file descriptor so we can keep a reference to it after the Parcel
927a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // is disposed.
928a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        int dupFd = dup(blob.fd());
929a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (dupFd < 0) {
930211abad3b92b70dd094949c79f67e686c940fa0cErik Wolsheimer            ALOGE("Error allocating dup fd. Error:%d", errno);
931a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
932a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            SkSafeUnref(ctable);
933a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate dup blob fd.");
934a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
93539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
936a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
937a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Map the pixels in place and take ownership of the ashmem region.
938c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
939c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
940a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
941a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
942a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            close(dupFd);
943a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
944a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate ashmem pixel ref.");
945a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
94639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
947a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
948a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Clear the blob handle, don't release it.
949a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.clear();
950a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
951a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
952a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (blob.fd() >= 0) {
953a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
954a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "from immutable blob (fds %s)",
955a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
956a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        } else {
957a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
958a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "(fds %s)",
959a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    blob.isMutable() ? "mutable" : "immutable",
960a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
96139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
962a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
963a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
964a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Copy the pixels into a new buffer.
965c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
966a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
967a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
968a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
969a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate java pixel ref.");
970a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
97139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
972a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->lockPixels();
973a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(bitmap->getPixels(), blob.data(), size);
974a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->unlockPixels();
975a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
976a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Release the blob handle.
977a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.release();
97839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
979a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
980c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(),
981a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
982a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown}
98339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
98432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
98532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jlong bitmapHandle,
98632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jboolean isMutable, jint density,
98732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jobject parcel) {
98832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
98932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("------- writeToParcel null parcel\n");
99032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
99132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
99232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
99332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
994f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
99539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
996c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
997c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmapWrapper->getSkBitmap(&bitmap);
99832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
999ab12c1fe73734a18ac19a06b97f276528f6d027aMike Reed    sk_sp<SkColorSpace> sRGB = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named);
1000253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    bool isSRGB = bitmap.colorSpace() == sRGB.get();
1001253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy
100232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(isMutable);
1003f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.colorType());
1004f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.alphaType());
1005253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    p->writeInt32(isSRGB); // TODO: We should write the color space (b/32072280)
1006f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.width());
1007f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.height());
1008f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.rowBytes());
100932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(density);
101032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1011f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap.colorType() == kIndex_8_SkColorType) {
101266ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        // The bitmap needs to be locked to access its color table.
101366ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        SkAutoLockPixels alp(bitmap);
1014f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ctable = bitmap.getColorTable();
101532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ctable != NULL) {
101632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            int count = ctable->count();
101732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(count);
101832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
101971487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed                   ctable->readColors(), count * sizeof(SkPMColor));
102032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        } else {
102132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(0);   // indicate no ctable
102232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
102332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
102432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1025a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Transfer the underlying ashmem region if we have one and it's immutable.
1026a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status;
1027aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    int fd = bitmapWrapper->bitmap().getAshmemFd();
1028a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (fd >= 0 && !isMutable && p->allowFds()) {
1029a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1030a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1031a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "immutable blob (fds %s)",
1032a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
1033a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1034a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1035a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        status = p->writeDupImmutableBlobFileDescriptor(fd);
1036a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (status) {
1037a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not write bitmap blob file descriptor.");
103839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews            return JNI_FALSE;
103939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1040a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_TRUE;
1041a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
104232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1043a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Copy the bitmap to a new blob.
1044a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bool mutableCopy = isMutable;
1045a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1046a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1047a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            isMutable ? "mutable" : "immutable",
1048a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            mutableCopy ? "mutable" : "immutable",
1049a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            p->allowFds() ? "allowed" : "forbidden");
1050a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1051a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1052a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap.getSize();
1053a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::WritableBlob blob;
1054a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    status = p->writeBlob(size, mutableCopy, &blob);
1055a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
1056a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not copy bitmap to parcel blob.");
1057a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_FALSE;
105839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
1059a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1060a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.lockPixels();
1061a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    const void* pSrc =  bitmap.getPixels();
1062a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (pSrc == NULL) {
1063a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memset(blob.data(), 0, size);
1064a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
1065a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(blob.data(), pSrc, size);
1066a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
1067a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.unlockPixels();
1068a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1069a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    blob.release();
107032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
107132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
107232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
107332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
107432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jlong srcHandle, jlong paintHandle,
107532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jintArray offsetXY) {
1076f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
1077c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
10786ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
107932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkIPoint  offset;
1080f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap dst;
10814508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
108232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1083f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    src.extractAlpha(&dst, paint, &allocator, &offset);
108432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // If Skia can't allocate pixels for destination bitmap, it resets
108532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // it, that is set its pixels buffer to NULL, and zero width and height.
1086f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
108732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowOOME(env, "failed to allocate pixels for alpha");
108832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
108932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
109032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
109132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int* array = env->GetIntArrayElements(offsetXY, NULL);
109232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[0] = offset.fX;
109332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[1] = offset.fY;
109432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        env->ReleaseIntArrayElements(offsetXY, array, 0);
109532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
109632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1097c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, allocator.getStorageObjAndReset(),
1098f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(true));
109932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
110032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
110132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
110232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
110332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
110457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y) {
1105f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1106c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1107f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
110832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1109f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
111032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
111132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
111232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1113f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
111432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
111532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
111632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
111732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
111832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor dst[1];
1119f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(dst, src, 1, bitmap.getColorTable());
112032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(dst[0]);
112132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
112232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
112332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
112432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
112557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1126f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1127c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1128f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
112932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1130f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
113132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
113232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
113332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1134f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
113532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
113632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
113732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
113832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1139f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkColorTable* ctable = bitmap.getColorTable();
114032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
114132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor* d = (SkColor*)dst + offset;
114232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    while (--height >= 0) {
114332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        proc(d, src, width, ctable);
114432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        d += stride;
1145f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        src = (void*)((const char*)src + bitmap.rowBytes());
114632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
114732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(pixelArray, dst, 0);
114832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
114932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
115032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
115132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
115232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
115357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint colorHandle) {
1154f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1155c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
115632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor color = static_cast<SkColor>(colorHandle);
1157f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1158f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bitmap.getPixels()) {
115932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
116032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
116132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1162f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    FromColorProc proc = ChooseFromColorProc(bitmap);
116332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
116432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
116532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
116632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1167f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1168f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap.notifyPixelsChanged();
116932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
117032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
117132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
117232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
117357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1174f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1175c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
117632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1177f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            x, y, width, height, bitmap);
117832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
117932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
118032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
118132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                      jlong bitmapHandle, jobject jbuffer) {
1182f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1183c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1184f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1185f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getPixels();
118632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
118732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != src) {
118832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
118932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
119032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1191f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(abp.pointer(), src, bitmap.getSize());
119232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
119332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
119432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
119532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
119632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                        jlong bitmapHandle, jobject jbuffer) {
1197f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1198c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1199f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1200f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* dst = bitmap.getPixels();
120132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
120232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != dst) {
120332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
120432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1205f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(dst, abp.pointer(), bitmap.getSize());
1206f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bitmap.notifyPixelsChanged();
120732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
120832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
120932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1210795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craikstatic jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
1211f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm0;
1212f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm1;
12131eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
12141eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    LocalScopedBitmap bitmap0(bm0Handle);
12151eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    LocalScopedBitmap bitmap1(bm1Handle);
12161eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
12171eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // Paying the price for making Hardware Bitmap as Config:
12181eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // later check for colorType will pass successfully,
12191eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // because Hardware Config internally may be RGBA8888 or smth like that.
122015a108550e3d74b406927d85c8e69018761adf49sergeyv    if (bitmap0->isHardware() != bitmap1->isHardware()) {
12211eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv        return JNI_FALSE;
12221eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    }
12231eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
12241eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    bitmap0->bitmap().getSkBitmap(&bm0);
12251eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    bitmap1->bitmap().getSkBitmap(&bm1);
1226795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik    if (bm0.width() != bm1.width()
1227795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.height() != bm1.height()
1228795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.colorType() != bm1.colorType()
1229795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.alphaType() != bm1.alphaType()
1230795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
123132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
123232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
123332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1234f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp0(bm0);
1235f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp1(bm1);
123632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
123732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // if we can't load the pixels, return false
1238f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
123932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
124032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
124132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1242f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bm0.colorType() == kIndex_8_SkColorType) {
1243f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct0 = bm0.getColorTable();
1244f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct1 = bm1.getColorTable();
124532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (NULL == ct0 || NULL == ct1) {
124632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
124732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
124832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ct0->count() != ct1->count()) {
124932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
125032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
125132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
125232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        const size_t size = ct0->count() * sizeof(SkPMColor);
125371487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
125432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
125532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
125632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
125732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
125832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now compare each scanline. We can't do the entire buffer at once,
125932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // since we don't care about the pixel values that might extend beyond
126032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // the width (since the scanline might be larger than the logical width)
1261f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const int h = bm0.height();
1262f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const size_t size = bm0.width() * bm0.bytesPerPixel();
126332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < h; y++) {
126453001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
126553001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
126653001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
126753001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
126853001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // to warn user those 2 unrecognized config bitmaps may be different.
1269f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm0Addr = bm0.getAddr(0, y);
1270f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm1Addr = bm1.getAddr(0, y);
127153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
127253001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if(bm0Addr == NULL || bm1Addr == NULL) {
127353001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen            return JNI_FALSE;
127453001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        }
127553001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
127653001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
127732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
127832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
127932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
128032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
128132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
128232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
12834387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reckstatic void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
12844387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    LocalScopedBitmap bitmapHandle(bitmapPtr);
12854387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    if (!bitmapHandle.valid()) return;
1286ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
12874387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck}
12884387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck
12894508218850faedea95371188da587b6734f5f3dasergeyvstatic jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
12904508218850faedea95371188da587b6734f5f3dasergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
12914508218850faedea95371188da587b6734f5f3dasergeyv    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
12924508218850faedea95371188da587b6734f5f3dasergeyv}
12934508218850faedea95371188da587b6734f5f3dasergeyv
129432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
1295c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass make_globalref(JNIEnv* env, const char classname[])
1296c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1297c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jclass c = env->FindClass(classname);
1298c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(c);
1299c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return (jclass) env->NewGlobalRef(c);
1300c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
1301c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
1302c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1303c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv                                const char fieldname[], const char type[])
1304c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1305c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jfieldID id = env->GetFieldID(clazz, fieldname, type);
1306c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(id);
1307c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return id;
1308c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
130932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
131076f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gBitmapMethods[] = {
131132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
131232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_creator },
131332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
131432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_copy },
1315721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1316721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        (void*)Bitmap_copyAshmem },
1317a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1318a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson        (void*)Bitmap_copyAshmemConfig },
1319775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
132032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
13214508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
132232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
132332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_compress },
132432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
132532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
132632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
132732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
132857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
132957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
133057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
133132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
133232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
133332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreateFromParcel",
133432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
133532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_createFromParcel },
133632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
133732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_writeToParcel },
133832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
133932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_extractAlpha },
134032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
134157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
134257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
134357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
134457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
134532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
134632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsToBuffer },
134732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
134832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsFromBuffer },
134932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
13504387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
13514508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
135232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
135332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
135432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikint register_android_graphics_Bitmap(JNIEnv* env)
135532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik{
1356c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1357c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1358c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1359c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1360c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
1361ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1362ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                         NELEM(gBitmapMethods));
13639192d5e8d78b826a665ce048c007e6eaf0f5b003John Reck}
1364