Bitmap.cpp revision d70532d123b816e0f2ae482258b4e3af56fcdcb2
1f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#define LOG_TAG "Bitmap"
2f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#include "Bitmap.h"
3f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
40a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv#include "GraphicBuffer.h"
532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkBitmap.h"
632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkPixelRef.h"
732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkImageEncoder.h"
857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III#include "SkImageInfo.h"
99505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkColor.h"
1032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkColorPriv.h"
11ce217faddb4b40c1b3e698944da1951027080427Romain Guy#include "SkColorSpace.h"
12ce217faddb4b40c1b3e698944da1951027080427Romain Guy#include "SkColorSpaceXform.h"
139505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkHalf.h"
14efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy#include "SkMatrix44.h"
159505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkPM4f.h"
169505a6552764461c22ce48f1ac13d025d23e1579Romain Guy#include "SkPM4fPriv.h"
1732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "GraphicsJNI.h"
1832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkDither.h"
1932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkUnPreMultiply.h"
2032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkStream.h"
2132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
2232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <binder/Parcel.h>
2332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_os_Parcel.h"
2432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_util_Binder.h"
2532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_nio_utils.h"
2632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "CreateJavaOutputStreamAdaptor.h"
27dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
28c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv#include <hwui/Bitmap.h>
294387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck#include <renderthread/RenderProxy.h>
3032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
31ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
32ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
3332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <jni.h>
34ce217faddb4b40c1b3e698944da1951027080427Romain Guy#include <string.h>
3539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <memory>
3639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <string>
3732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#define DEBUG_PARCEL 0
398cee7c17119b204be88860feb812f2374d0de732Riley Andrews#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
40a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
41c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass   gBitmap_class;
42c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID gBitmap_nativePtr;
43c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_constructorMethodID;
44c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_reinitMethodID;
45c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_getAllocationByteCountMethodID;
46c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
47f29ed28c7b878ef28058bc730715d0d32445bc57John Recknamespace android {
48f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
49c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvclass BitmapWrapper {
50f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
51c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper(Bitmap* bitmap)
52c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        : mBitmap(bitmap) { }
53c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
54c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void freePixels() {
55c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mInfo = mBitmap->info();
56c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mHasHardwareMipMap = mBitmap->hasHardwareMipMap();
57c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mAllocationSize = mBitmap->getAllocationByteCount();
58c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mRowBytes = mBitmap->rowBytes();
59c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mGenerationId = mBitmap->getGenerationID();
6015a108550e3d74b406927d85c8e69018761adf49sergeyv        mIsHardware = mBitmap->isHardware();
61c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap.reset();
62f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
63f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
64c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool valid() {
65fc9999505a36c66892d7ccce85187936105f4f36sergeyv        return mBitmap;
66f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
67f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
68aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    Bitmap& bitmap() {
69aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        assertValid();
70aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return *mBitmap;
71aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
72c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
73c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void assertValid() {
74c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
75c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
76c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
77c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void getSkBitmap(SkBitmap* outBitmap) {
78c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
79c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->getSkBitmap(outBitmap);
80c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
810781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
82c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool hasHardwareMipMap() {
83c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
84c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->hasHardwareMipMap();
85c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
86f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mHasHardwareMipMap;
87f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
88f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
89f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void setHasHardwareMipMap(bool hasMipMap) {
90c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
91c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setHasHardwareMipMap(hasMipMap);
92f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
93f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
94c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void setAlphaType(SkAlphaType alphaType) {
95c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
96c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        mBitmap->setAlphaType(alphaType);
97f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
98f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
99c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    const SkImageInfo& info() {
100c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
101c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->info();
102c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
103c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mInfo;
104f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
105f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
106c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t getAllocationByteCount() const {
107c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
108c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getAllocationByteCount();
109c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
110c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mAllocationSize;
111f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
112f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
113c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t rowBytes() const {
114c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
115c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->rowBytes();
116c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
117c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mRowBytes;
118c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
119f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
120c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t getGenerationID() const {
121c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        if (mBitmap) {
122c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            return mBitmap->getGenerationID();
123c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
124c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mGenerationId;
125f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
126c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
12715a108550e3d74b406927d85c8e69018761adf49sergeyv    bool isHardware() {
12815a108550e3d74b406927d85c8e69018761adf49sergeyv        if (mBitmap) {
12915a108550e3d74b406927d85c8e69018761adf49sergeyv            return mBitmap->isHardware();
13015a108550e3d74b406927d85c8e69018761adf49sergeyv        }
13115a108550e3d74b406927d85c8e69018761adf49sergeyv        return mIsHardware;
13215a108550e3d74b406927d85c8e69018761adf49sergeyv    }
13315a108550e3d74b406927d85c8e69018761adf49sergeyv
134c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    ~BitmapWrapper() { }
135c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
136c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvprivate:
137c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> mBitmap;
138c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkImageInfo mInfo;
139c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool mHasHardwareMipMap;
140c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mAllocationSize;
141c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mRowBytes;
142c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t mGenerationId;
14315a108550e3d74b406927d85c8e69018761adf49sergeyv    bool mIsHardware;
144f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
145f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
146f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// Convenience class that does not take a global ref on the pixels, relying
147f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// on the caller already having a local JNI ref
148f29ed28c7b878ef28058bc730715d0d32445bc57John Reckclass LocalScopedBitmap {
149f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
150c6baf563ba6aa207a48317c177b29f1d2b70cf3dChih-Hung Hsieh    explicit LocalScopedBitmap(jlong bitmapHandle)
151c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            : mBitmapWrapper(reinterpret_cast<BitmapWrapper*>(bitmapHandle)) {}
152f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
153c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* operator->() {
154c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper;
155f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
156f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
157f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* pixels() {
158aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return mBitmapWrapper->bitmap().pixels();
159f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
160f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
161f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool valid() {
162c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        return mBitmapWrapper && mBitmapWrapper->valid();
163f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
164f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
165f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprivate:
166c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* mBitmapWrapper;
167f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
168f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
169c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvnamespace bitmap {
170c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
171c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
172c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
173c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
174c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // irrelevant. This just tests to ensure that the SkAlphaType is not
175c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // opposite of isPremultiplied.
176c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isPremultiplied) {
177c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
178c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    } else {
179c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
180c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
181c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
182c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
183c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
184c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        bool isPremultiplied)
185c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
186c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
187c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
188c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    assert_premultiplied(info, isPremultiplied);
189c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
190c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
191c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            info.width(), info.height(), isPremultiplied);
192c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
193c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
194c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvint getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
195c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
196c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
197c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
198c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
199c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvjobject createBitmap(JNIEnv* env, Bitmap* bitmap,
200c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
201c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int density) {
202c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
203c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
204c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
205c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
206c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    assert_premultiplied(bitmap->info(), isPremultiplied);
207c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    BitmapWrapper* bitmapWrapper = new BitmapWrapper(bitmap);
208c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
209c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
210c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv            isMutable, isPremultiplied, ninePatchChunk, ninePatchInsets);
211c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
212c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (env->ExceptionCheck() != 0) {
213c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        ALOGE("*** Uncaught exception returned from Java call!\n");
214c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        env->ExceptionDescribe();
215c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
216c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return obj;
217c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
218c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
219c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
220c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap bitmap(bitmapHandle);
221c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->getSkBitmap(outBitmap);
222c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
223c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
224aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyvBitmap& toBitmap(JNIEnv* env, jobject bitmap) {
225c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env);
226c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(bitmap);
227c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
228c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
229c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
230c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return localBitmap->bitmap();
231c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
232c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
2335fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyvBitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
2345fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    SkASSERT(env);
2355fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
2365fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv    return localBitmap->bitmap();
2375fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv}
2385fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv
23900799f760d6956fc54ee1763427f8196fcb3696dJohn Reckvoid imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
24000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(info);
24100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env);
24200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(bitmap);
24300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
24400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
24500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    LocalScopedBitmap localBitmap(bitmapHandle);
24600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
24700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    const SkImageInfo& imageInfo = localBitmap->info();
24800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->width = imageInfo.width();
24900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->height = imageInfo.height();
25000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->stride = localBitmap->rowBytes();
25100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    info->flags = 0;
25200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    switch (imageInfo.colorType()) {
25300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kN32_SkColorType:
25400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
25500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
25600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kRGB_565_SkColorType:
25700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
25800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
25900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kARGB_4444_SkColorType:
26000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
26100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
26200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        case kAlpha_8_SkColorType:
26300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_A_8;
26400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
26500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        default:
26600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            info->format = ANDROID_BITMAP_FORMAT_NONE;
26700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck            break;
26800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    }
26900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck}
27000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
27100799f760d6956fc54ee1763427f8196fcb3696dJohn Reckvoid* lockPixels(JNIEnv* env, jobject bitmap) {
27200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env);
27300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(bitmap);
27400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
27500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
27600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
27700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    LocalScopedBitmap localBitmap(bitmapHandle);
27800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    if (!localBitmap->valid()) return nullptr;
27900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
28000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkPixelRef& pixelRef = localBitmap->bitmap();
28100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.lockPixels();
28200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    if (!pixelRef.pixels()) {
28300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        pixelRef.unlockPixels();
28400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck        return nullptr;
28500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    }
28600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.ref();
28700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    return pixelRef.pixels();
28800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck}
28900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
29000799f760d6956fc54ee1763427f8196fcb3696dJohn Reckbool unlockPixels(JNIEnv* env, jobject bitmap) {
29100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env);
29200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(bitmap);
29300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
29400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
29500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
29600799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    LocalScopedBitmap localBitmap(bitmapHandle);
29700799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    if (!localBitmap->valid()) return false;
29800799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
29900799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    SkPixelRef& pixelRef = localBitmap->bitmap();
30000799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.notifyPixelsChanged();
30100799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.unlockPixels();
30200799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    pixelRef.unref();
30300799f760d6956fc54ee1763427f8196fcb3696dJohn Reck    return true;
30400799f760d6956fc54ee1763427f8196fcb3696dJohn Reck}
30500799f760d6956fc54ee1763427f8196fcb3696dJohn Reck
306c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace bitmap
307c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
308c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace android
309c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
310c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android;
311c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android::bitmap;
312c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
31332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
31432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// Conversions to/from SkColor, for get/setPixels, and the create method, which
31532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// is basically like setPixels
31632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
31732054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
31832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              int x, int y);
31932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
3209505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void FromColor_F16(void* dst, const SkColor src[], int width,
3219505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                          int, int) {
3229505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* d = (uint64_t*)dst;
3239505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
3249505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    for (int i = 0; i < width; i++) {
3259505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
3269505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
3279505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
3289505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
3299505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
3309505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                          int, int) {
3319505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* d = (uint64_t*)dst;
3329505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
3339505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    for (int i = 0; i < width; i++) {
3349505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        const float* color = SkColor4f::FromColor(*src++).vec();
3359505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
3369505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        for (int i = 0; i < 4; ++i) {
3379505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            scratch[i] = SkFloatToHalf(color[i]);
3389505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        }
3399505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
3409505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
3419505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
34232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32(void* dst, const SkColor src[], int width,
34332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
34432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
34532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
34632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
34732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPreMultiplyColor(*src++);
34832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
34932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
35032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
35132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
35232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
35346d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    // Needed to thwart the unreachable code detection from clang.
35446d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
35546d8444631b4b1253a76bfcc78a29d26014d022fDan Albert
35632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // SkColor's ordering may be different from SkPMColor
35746d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    if (sk_color_ne_zero) {
35832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        memcpy(dst, src, width * sizeof(SkColor));
35932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
36032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
36132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
36232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // order isn't same, repack each pixel manually
36332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
36432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
36532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
36632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
36732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   SkColorGetG(c), SkColorGetB(c));
36832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
36932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
37032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D565(void* dst, const SkColor src[], int width,
37232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           int x, int y) {
37332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    uint16_t* d = (uint16_t*)dst;
37432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_565_SCAN(y);
37632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
37732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
37832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
37932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                DITHER_VALUE(x));
38032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
38132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
38232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444(void* dst, const SkColor src[], int width,
38432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
38532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
38632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
38832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
38932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPreMultiplyColor(*src++);
39032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
39132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
39232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
39332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
39432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
39632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
39732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
39832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
40032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
40132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
40232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
40332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
40432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
40532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            SkColorGetG(c), SkColorGetB(c));
40632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
40732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
40832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
40932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
41032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4116260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
4126260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    uint8_t* d = (uint8_t*)dst;
4136260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
4146260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    for (int stop = x + width; x < stop; x++) {
4156260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *d++ = SkColorGetA(*src++);
4166260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    }
4176260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
4186260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
41932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
42057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
42157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    switch (bitmap.colorType()) {
42257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kN32_SkColorType:
42357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
42457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kARGB_4444_SkColorType:
42557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
42657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    FromColor_D4444_Raw;
42757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kRGB_565_SkColorType:
42832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return FromColor_D565;
4296260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
4306260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return FromColor_DA8;
4319505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        case kRGBA_F16_SkColorType:
4329505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
43332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
43432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
43532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
43632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
43732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
43832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikbool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
44057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
44132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkAutoLockPixels alp(dstBitmap);
44232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    void* dst = dstBitmap.getPixels();
44357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    FromColorProc proc = ChooseFromColorProc(dstBitmap);
44432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == dst || NULL == proc) {
44632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return false;
44732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
44832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
44932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const jint* array = env->GetIntArrayElements(srcColors, NULL);
45032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkColor* src = (const SkColor*)array + srcOffset;
45132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
45232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // reset to to actual choice from caller
45332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dst = dstBitmap.getAddr(x, y);
454ce217faddb4b40c1b3e698944da1951027080427Romain Guy
455ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = dstBitmap.colorSpace();
456d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy    if (dstBitmap.colorType() == kRGBA_F16_SkColorType ||
457d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
458ce217faddb4b40c1b3e698944da1951027080427Romain Guy        // now copy/convert each scanline
459ce217faddb4b40c1b3e698944da1951027080427Romain Guy        for (int y = 0; y < height; y++) {
460ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(dst, src, width, x, y);
461ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src += srcStride;
462ce217faddb4b40c1b3e698944da1951027080427Romain Guy            dst = (char*)dst + dstBitmap.rowBytes();
463ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
464ce217faddb4b40c1b3e698944da1951027080427Romain Guy    } else {
465ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
466ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
467ce217faddb4b40c1b3e698944da1951027080427Romain Guy
468ce217faddb4b40c1b3e698944da1951027080427Romain Guy        std::unique_ptr<SkColor[]> row(new SkColor[width]);
469ce217faddb4b40c1b3e698944da1951027080427Romain Guy
470ce217faddb4b40c1b3e698944da1951027080427Romain Guy        // now copy/convert each scanline
471ce217faddb4b40c1b3e698944da1951027080427Romain Guy        for (int y = 0; y < height; y++) {
472ce217faddb4b40c1b3e698944da1951027080427Romain Guy            memcpy(row.get(), src, sizeof(SkColor) * width);
473ce217faddb4b40c1b3e698944da1951027080427Romain Guy            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
474ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
475ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkAlphaType::kUnpremul_SkAlphaType);
476ce217faddb4b40c1b3e698944da1951027080427Romain Guy
477ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(dst, row.get(), width, x, y);
478ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src += srcStride;
479ce217faddb4b40c1b3e698944da1951027080427Romain Guy            dst = (char*)dst + dstBitmap.rowBytes();
480ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
48132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
48232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
48332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dstBitmap.notifyPixelsChanged();
48432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4859505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
48632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return true;
48732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
48832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
48932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//////////////////// ToColor procs
49032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
49132054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
49232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            SkColorTable*);
49332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4949505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
4959505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                              SkColorTable*) {
4969505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    SkASSERT(width > 0);
4979505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* s = (uint64_t*)src;
4989505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    do {
4999505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
5009505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    } while (--width != 0);
5019505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
5029505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
5039505a6552764461c22ce48f1ac13d025d23e1579Romain Guystatic void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
5049505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                            SkColorTable*) {
5059505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    SkASSERT(width > 0);
5069505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    uint64_t* s = (uint64_t*)src;
5079505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    do {
5089505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
5099505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    } while (--width != 0);
5109505a6552764461c22ce48f1ac13d025d23e1579Romain Guy}
5119505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
51232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
51332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
51432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
51532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
51632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
51732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
51832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
51932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
52032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
52132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
52232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
52332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
52432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
52532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
52632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
52732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
52832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
52932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
53032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
53132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
53232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
53332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable*) {
53432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
53532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
53632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
53732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
53832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
53932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
54032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
54132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
54232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
54332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
54432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
54532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
54632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
54732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
54832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
54932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
55032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
55132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
55232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
55332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
55432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
55532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
55632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
55732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
55832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
55932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
56032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
56132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
56232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
56332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
56432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 SkColorTable*) {
56532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
56632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
56732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
56832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
56932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
57032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
57132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
57232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
57332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
57432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S565(SkColor dst[], const void* src, int width,
57532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                         SkColorTable*) {
57632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
57732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint16_t* s = (const uint16_t*)src;
57832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
57932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        uint16_t c = *s++;
58032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
58132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkPacked16ToB32(c));
58232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
58332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
58432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
58532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
58632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
58732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
58832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
58971487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
59032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
59132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
59232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
59332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
59432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
59532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
59632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
59732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
59832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
59971487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
60032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
60132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
60232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
60332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
60432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
60532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
60632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
60732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
60832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable* ctable) {
60932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
61032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
61171487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
61232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
61332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
61432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
61532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
61632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
61732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
61832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
6196260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
6206260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    SkASSERT(width > 0);
6216260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    const uint8_t* s = (const uint8_t*)src;
6226260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    do {
6236260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        uint8_t c = *s++;
6246260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *dst++ = SkColorSetARGB(c, c, c, c);
6256260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    } while (--width != 0);
6266260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
6276260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
62832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
62957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic ToColorProc ChooseToColorProc(const SkBitmap& src) {
630b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    switch (src.colorType()) {
631b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kN32_SkColorType:
63257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
63357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
63457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Opaque;
63557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
63657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Alpha;
63757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
63857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Raw;
63957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
64057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
64157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
642b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kARGB_4444_SkColorType:
64357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
64457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
64557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Opaque;
64657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
64757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Alpha;
64857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
64957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Raw;
65057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
65157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
65257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
653b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kRGB_565_SkColorType:
65432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return ToColor_S565;
655b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kIndex_8_SkColorType:
65632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            if (src.getColorTable() == NULL) {
65732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                return NULL;
65832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            }
65957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
66057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
66157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Opaque;
66257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
66357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Alpha;
66457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
66557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Raw;
66657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
66757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
66857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
6696260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
6706260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return ToColor_SA8;
6719505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        case kRGBA_F16_SkColorType:
6729505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            switch (src.alphaType()) {
6739505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kOpaque_SkAlphaType:
6749505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Raw;
6759505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kPremul_SkAlphaType:
6769505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Alpha;
6779505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                case kUnpremul_SkAlphaType:
6789505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return ToColor_F16_Raw;
6799505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                default:
6809505a6552764461c22ce48f1ac13d025d23e1579Romain Guy                    return NULL;
6819505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            }
68232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
68332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
68432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
68532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
68632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
68732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
68832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
68932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
69032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic int getPremulBitmapCreateFlags(bool isMutable) {
692c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
693c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
69432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return flags;
69532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
69632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
69832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint offset, jint stride, jint width, jint height,
69932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint configHandle, jboolean isMutable) {
7001103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
70132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != jColors) {
70232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        size_t n = env->GetArrayLength(jColors);
70332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (n < SkAbs32(stride) * (size_t)height) {
70432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            doThrowAIOOBE(env);
70532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return NULL;
70632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
70732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
70832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
70932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // ARGB_4444 is a deprecated format, convert automatically to 8888
710b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kARGB_4444_SkColorType) {
711b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        colorType = kN32_SkColorType;
71232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
71332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
71432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkBitmap bitmap;
715253f2c213f6ecda63b6872aee77bd30d5ec07c82Romain Guy    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
7169505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            GraphicsJNI::colorSpaceForType(colorType)));
71732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
718c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
719f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!nativeBitmap) {
72032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
72132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
72232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
72332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (jColors != NULL) {
7249505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
72532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
72632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
727c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
72832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
72932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
73032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
73132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           jint dstConfigHandle, jboolean isMutable) {
732f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
733c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
73405126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv    if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) {
73505126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src));
73605126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        if (!bitmap.get()) {
73705126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv            return NULL;
73805126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv        }
739656117bed2fc1937bcebd615898924ed57c48979sergeyv        return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable));
74005126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv    }
74105126d151eb3caa85bd3a039cffb6e37940c3fa4sergeyv
7421103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
7434508218850faedea95371188da587b6734f5f3dasergeyv    SkBitmap result;
7444508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
74532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
746f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!src.copyTo(&result, dstCT, &allocator)) {
74732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
74832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
749c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
750c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable));
75132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
75232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
753c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
754721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    SkBitmap result;
755721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
756721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    AshmemPixelAllocator allocator(env);
757a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    if (!src.copyTo(&result, dstCT, &allocator)) {
758721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        return NULL;
759721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    }
760c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = allocator.getStorageObjAndReset();
761c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmap->setImmutable();
762c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    return bitmap;
763a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
764a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
765a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
766a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
767c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
768a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = src.colorType();
769c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
770c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
771a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    return ret;
772a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
773a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
774a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
775a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
776c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
777a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
778c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT);
779c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false));
780721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    return ret;
781721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews}
782721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
783c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyvstatic void Bitmap_destruct(BitmapWrapper* bitmap) {
784c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    delete bitmap;
78532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
78632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
787775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
788775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
789775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler}
790775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
79132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
792f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
793f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->freePixels();
79432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
79532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
79632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
79732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
7984508218850faedea95371188da587b6734f5f3dasergeyv        jint width, jint height, jint configHandle, jboolean requestPremul) {
799f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
800c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->assertValid();
8011103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
80217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III
80317a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    // ARGB_4444 is a deprecated format, convert automatically to 8888
80417a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    if (colorType == kARGB_4444_SkColorType) {
80517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        colorType = kN32_SkColorType;
80617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
8074508218850faedea95371188da587b6734f5f3dasergeyv    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
8084508218850faedea95371188da587b6734f5f3dasergeyv    if (requestedSize > bitmap->getAllocationByteCount()) {
80932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // done in native as there's no way to get BytesPerPixel in Java
81032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowIAE(env, "Bitmap not large enough to support new configuration");
81132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
81232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
81317a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    SkAlphaType alphaType;
814f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().colorType() != kRGB_565_SkColorType
815f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
81617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // If the original bitmap was set to opaque, keep that setting, unless it
81717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // was 565, which is required to be opaque.
81817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = kOpaque_SkAlphaType;
81917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    } else {
82017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // Otherwise respect the premultiplied request.
82117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
82217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
823aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    bitmap->bitmap().reconfigure(SkImageInfo::Make(width, height, colorType, alphaType,
8247d5219fb505ff1b178910cda25a40154e7d4d09asergeyv            sk_ref_sp(bitmap->info().colorSpace())));
82532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
82632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
82732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// These must match the int values in Bitmap.java
82832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikenum JavaEncodeFormat {
82932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kJPEG_JavaEncodeFormat = 0,
83032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kPNG_JavaEncodeFormat = 1,
83132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kWEBP_JavaEncodeFormat = 2
83232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
83332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
83432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
83532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jint format, jint quality,
83632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jobject jstream, jbyteArray jstorage) {
83710219fb261606fcc71c607167b28295b4578a10dHal Canary    SkEncodedImageFormat fm;
83832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    switch (format) {
83932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kJPEG_JavaEncodeFormat:
84010219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kJPEG;
84132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kPNG_JavaEncodeFormat:
84310219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kPNG;
84432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kWEBP_JavaEncodeFormat:
84610219fb261606fcc71c607167b28295b4578a10dHal Canary        fm = SkEncodedImageFormat::kWEBP;
84732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
84832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    default:
84932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
85032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
85132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
85210219fb261606fcc71c607167b28295b4578a10dHal Canary    LocalScopedBitmap bitmap(bitmapHandle);
853f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap.valid()) {
854f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
855f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
85632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
857f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
858f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!strm.get()) {
859f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
860f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
86132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
86210219fb261606fcc71c607167b28295b4578a10dHal Canary    SkBitmap skbitmap;
86310219fb261606fcc71c607167b28295b4578a10dHal Canary    bitmap->getSkBitmap(&skbitmap);
86410219fb261606fcc71c607167b28295b4578a10dHal Canary    return SkEncodeImage(strm.get(), skbitmap, fm, quality) ? JNI_TRUE : JNI_FALSE;
86532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
86632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
86732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
868f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
869f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap skBitmap;
870f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->getSkBitmap(&skBitmap);
871f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    skBitmap.eraseColor(color);
87232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
87332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
87432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
875f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
87632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(bitmap->rowBytes());
87732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
87832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
87932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
880f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
88115a108550e3d74b406927d85c8e69018761adf49sergeyv    if (bitmap->isHardware()) {
88219b4b019169424d62bf3edc40b9560984206cf80sergeyv        return GraphicsJNI::hardwareLegacyBitmapConfig();
88319b4b019169424d62bf3edc40b9560984206cf80sergeyv    }
884f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
88532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
88632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
88732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
888f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
889c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return static_cast<jint>(bitmap->getGenerationID());
89032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
89132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
89257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
893f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
894f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
89557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        return JNI_TRUE;
89657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
89757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    return JNI_FALSE;
89857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
89957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
90032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
901f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
902f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
90332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
90432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
90557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
90657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean hasAlpha, jboolean requestPremul) {
907f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
90857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    if (hasAlpha) {
9090781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(
910f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
91132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } else {
9120781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(kOpaque_SkAlphaType);
91357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
91457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
91557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
91657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
91757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean isPremul) {
918f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
919f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap->info().isOpaque()) {
92057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        if (isPremul) {
9210781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kPremul_SkAlphaType);
92257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        } else {
9230781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kUnpremul_SkAlphaType);
92457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        }
92532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
92632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
92732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
92832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
929f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
93032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
93132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
93232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
93332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
93432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jboolean hasMipMap) {
935f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
93632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    bitmap->setHasHardwareMipMap(hasMipMap);
93732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
93832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
93932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
94032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
94132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
94232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
94332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("-------- unparcel parcel is NULL\n");
94432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
94532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
94632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
94732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
94832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
949b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const bool        isMutable = p->readInt32() != 0;
950b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkColorType colorType = (SkColorType)p->readInt32();
951b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
9525acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    const uint32_t    colorSpaceSize = p->readUint32();
9535acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    sk_sp<SkColorSpace> colorSpace;
9545acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    if (kRGBA_F16_SkColorType == colorType) {
9555acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        colorSpace = SkColorSpace::MakeSRGBLinear();
9565acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    } else if (colorSpaceSize > 0) {
9575acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        colorSpace = SkColorSpace::Deserialize(p->readInplace(colorSpaceSize), colorSpaceSize);
9585acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    }
959b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         width = p->readInt32();
960b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         height = p->readInt32();
961b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         rowBytes = p->readInt32();
962b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         density = p->readInt32();
963b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed
964b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (kN32_SkColorType != colorType &&
9659505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            kRGBA_F16_SkColorType != colorType &&
966b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kRGB_565_SkColorType != colorType &&
967b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kARGB_4444_SkColorType != colorType &&
968b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kIndex_8_SkColorType != colorType &&
969b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kAlpha_8_SkColorType != colorType) {
970b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
97132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
97232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
97332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
974ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
9759505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
9769505a6552764461c22ce48f1ac13d025d23e1579Romain Guy            rowBytes)) {
977ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        return NULL;
978ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    }
97932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
98032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColorTable* ctable = NULL;
981b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kIndex_8_SkColorType) {
98232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int count = p->readInt32();
983ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        if (count < 0 || count > 256) {
984ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
985ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // inclusive.
986ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            return NULL;
987ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        }
98832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (count > 0) {
98932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            size_t size = count * sizeof(SkPMColor);
99032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
991ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            if (src == NULL) {
992ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III                return NULL;
993ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            }
99432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            ctable = new SkColorTable(src, count);
99532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
99632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
99732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
998a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Read the bitmap blob.
999a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap->getSize();
1000a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::ReadableBlob blob;
1001a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status = p->readBlob(size, &blob);
1002a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
100332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkSafeUnref(ctable);
1004a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not read bitmap blob.");
100532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
100632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
100732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1008a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Map the bitmap in place from the ashmem region if possible otherwise copy.
1009c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    sk_sp<Bitmap> nativeBitmap;
10108cee7c17119b204be88860feb812f2374d0de732Riley Andrews    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
1011a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1012a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
1013a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "(fds %s)",
1014a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                isMutable ? "mutable" : "immutable",
1015a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                blob.isMutable() ? "mutable" : "immutable",
1016a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
1017a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1018a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Dup the file descriptor so we can keep a reference to it after the Parcel
1019a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // is disposed.
1020a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        int dupFd = dup(blob.fd());
1021a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (dupFd < 0) {
1022211abad3b92b70dd094949c79f67e686c940fa0cErik Wolsheimer            ALOGE("Error allocating dup fd. Error:%d", errno);
1023a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1024a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            SkSafeUnref(ctable);
1025a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate dup blob fd.");
1026a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
102739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1028a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1029a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Map the pixels in place and take ownership of the ashmem region.
1030c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = sk_sp<Bitmap>(GraphicsJNI::mapAshmemBitmap(env, bitmap.get(),
1031c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable));
1032a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
1033a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
1034a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            close(dupFd);
1035a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1036a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate ashmem pixel ref.");
1037a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
103839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1039a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1040a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Clear the blob handle, don't release it.
1041a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.clear();
1042a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
1043a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1044a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (blob.fd() >= 0) {
1045a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
1046a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "from immutable blob (fds %s)",
1047a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
1048a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        } else {
1049a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
1050a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "(fds %s)",
1051a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    blob.isMutable() ? "mutable" : "immutable",
1052a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
105339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1054a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1055a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1056a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Copy the pixels into a new buffer.
1057c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv        nativeBitmap = Bitmap::allocateHeapBitmap(bitmap.get(), ctable);
1058a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
1059a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
1060a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1061a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate java pixel ref.");
1062a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
106339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1064a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->lockPixels();
1065a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(bitmap->getPixels(), blob.data(), size);
1066a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->unlockPixels();
1067a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1068a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Release the blob handle.
1069a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.release();
107039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
1071a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1072c36bd6c16ddfc160732ff7e4518564714c8aa66esergeyv    return createBitmap(env, nativeBitmap.release(),
1073a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
1074a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown}
107539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
107632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
107732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jlong bitmapHandle,
107832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jboolean isMutable, jint density,
107932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jobject parcel) {
108032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
108132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("------- writeToParcel null parcel\n");
108232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
108332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
108432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
108532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1086f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
108739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
1088c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
1089c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    bitmapWrapper->getSkBitmap(&bitmap);
109032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
109132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(isMutable);
1092f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.colorType());
1093f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.alphaType());
10945acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
10955acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    if (colorSpace != nullptr && bitmap.colorType() != kRGBA_F16_SkColorType) {
10965acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        sk_sp<SkData> data = colorSpace->serialize();
10975acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        size_t size = data->size();
10985acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        p->writeUint32(size);
10995acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        if (size > 0) {
11005acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy            p->write(data->data(), size);
11015acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        }
11025acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    } else {
11035acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy        p->writeUint32(0);
11045acc476878bce8b72c0059e05cbbd5b43ffee5d5Romain Guy    }
1105f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.width());
1106f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.height());
1107f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.rowBytes());
110832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(density);
110932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1110f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap.colorType() == kIndex_8_SkColorType) {
111166ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        // The bitmap needs to be locked to access its color table.
111266ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        SkAutoLockPixels alp(bitmap);
1113f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ctable = bitmap.getColorTable();
111432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ctable != NULL) {
111532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            int count = ctable->count();
111632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(count);
111732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
111871487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed                   ctable->readColors(), count * sizeof(SkPMColor));
111932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        } else {
112032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(0);   // indicate no ctable
112132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
112232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
112332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1124a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Transfer the underlying ashmem region if we have one and it's immutable.
1125a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status;
1126aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    int fd = bitmapWrapper->bitmap().getAshmemFd();
1127a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (fd >= 0 && !isMutable && p->allowFds()) {
1128a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1129a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1130a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "immutable blob (fds %s)",
1131a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
1132a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1133a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1134a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        status = p->writeDupImmutableBlobFileDescriptor(fd);
1135a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (status) {
1136a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not write bitmap blob file descriptor.");
113739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews            return JNI_FALSE;
113839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1139a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_TRUE;
1140a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
114132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1142a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Copy the bitmap to a new blob.
1143a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bool mutableCopy = isMutable;
1144a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1145a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1146a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            isMutable ? "mutable" : "immutable",
1147a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            mutableCopy ? "mutable" : "immutable",
1148a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            p->allowFds() ? "allowed" : "forbidden");
1149a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1150a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1151a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap.getSize();
1152a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::WritableBlob blob;
1153a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    status = p->writeBlob(size, mutableCopy, &blob);
1154a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
1155a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not copy bitmap to parcel blob.");
1156a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_FALSE;
115739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
1158a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1159a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.lockPixels();
1160a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    const void* pSrc =  bitmap.getPixels();
1161a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (pSrc == NULL) {
1162a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memset(blob.data(), 0, size);
1163a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
1164a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(blob.data(), pSrc, size);
1165a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
1166a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.unlockPixels();
1167a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1168a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    blob.release();
116932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
117032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
117132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
117232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
117332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jlong srcHandle, jlong paintHandle,
117432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jintArray offsetXY) {
1175f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
1176c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src);
11776ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
117832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkIPoint  offset;
1179f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap dst;
11804508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
118132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1182f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    src.extractAlpha(&dst, paint, &allocator, &offset);
118332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // If Skia can't allocate pixels for destination bitmap, it resets
118432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // it, that is set its pixels buffer to NULL, and zero width and height.
1185f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
118632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowOOME(env, "failed to allocate pixels for alpha");
118732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
118832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
118932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
119032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int* array = env->GetIntArrayElements(offsetXY, NULL);
119132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[0] = offset.fX;
119232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[1] = offset.fY;
119332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        env->ReleaseIntArrayElements(offsetXY, array, 0);
119432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
119532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1196c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, allocator.getStorageObjAndReset(),
1197f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(true));
119832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
119932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
120032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
120132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1202efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guystatic jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
1203efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    LocalScopedBitmap bitmapHolder(bitmapHandle);
1204efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!bitmapHolder.valid()) return JNI_TRUE;
1205efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1206efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1207ce217faddb4b40c1b3e698944da1951027080427Romain Guy    return GraphicsJNI::isColorSpaceSRGB(colorSpace);
1208efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy}
1209efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1210efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guystatic jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
1211efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy        jfloatArray xyzArray, jfloatArray paramsArray) {
1212efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1213efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    LocalScopedBitmap bitmapHolder(bitmapHandle);
1214efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!bitmapHolder.valid()) return JNI_FALSE;
1215efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1216efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
1217efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (colorSpace == nullptr) return JNI_FALSE;
1218efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1219efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
1220efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!colorSpace->toXYZD50(&xyzMatrix)) return JNI_FALSE;
1221efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1222efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    jfloat* xyz = env->GetFloatArrayElements(xyzArray, NULL);
1223efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[0] = xyzMatrix.getFloat(0, 0);
1224efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[1] = xyzMatrix.getFloat(1, 0);
1225efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[2] = xyzMatrix.getFloat(2, 0);
1226efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[3] = xyzMatrix.getFloat(0, 1);
1227efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[4] = xyzMatrix.getFloat(1, 1);
1228efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[5] = xyzMatrix.getFloat(2, 1);
1229efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[6] = xyzMatrix.getFloat(0, 2);
1230efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[7] = xyzMatrix.getFloat(1, 2);
1231efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    xyz[8] = xyzMatrix.getFloat(2, 2);
1232efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    env->ReleaseFloatArrayElements(xyzArray, xyz, 0);
1233efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1234efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    SkColorSpaceTransferFn transferParams;
1235efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    if (!colorSpace->isNumericalTransferFn(&transferParams)) return JNI_FALSE;
1236efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1237efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    jfloat* params = env->GetFloatArrayElements(paramsArray, NULL);
1238efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[0] = transferParams.fA;
1239efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[1] = transferParams.fB;
1240efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[2] = transferParams.fC;
1241efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[3] = transferParams.fD;
1242efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[4] = transferParams.fE;
1243efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[5] = transferParams.fF;
1244efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    params[6] = transferParams.fG;
1245efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    env->ReleaseFloatArrayElements(paramsArray, params, 0);
1246efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1247efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    return JNI_TRUE;
1248efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy}
1249efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
1250efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy///////////////////////////////////////////////////////////////////////////////
1251efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy
125232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
125357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y) {
1254f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1255c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1256f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
125732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1258f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
125932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
126032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
126132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1262f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
126332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
126432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
126532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
126632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
126732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor dst[1];
1268f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(dst, src, 1, bitmap.getColorTable());
1269ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1270ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
1271d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
1272d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1273ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
1274ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1275ce217faddb4b40c1b3e698944da1951027080427Romain Guy        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
1276ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
1277ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkAlphaType::kUnpremul_SkAlphaType);
1278ce217faddb4b40c1b3e698944da1951027080427Romain Guy    }
1279ce217faddb4b40c1b3e698944da1951027080427Romain Guy
128032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(dst[0]);
128132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
128232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
128332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
128432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
128557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1286f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1287c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1288f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
128932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1290f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
129132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
129232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
129332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1294f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
129532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
129632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
129732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
129832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1299f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkColorTable* ctable = bitmap.getColorTable();
130032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
130132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor* d = (SkColor*)dst + offset;
1302ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1303ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
1304d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy    if (bitmap.colorType() == kRGBA_F16_SkColorType ||
1305d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy            GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1306ce217faddb4b40c1b3e698944da1951027080427Romain Guy        while (--height >= 0) {
1307ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(d, src, width, ctable);
1308ce217faddb4b40c1b3e698944da1951027080427Romain Guy            d += stride;
1309ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src = (void*)((const char*)src + bitmap.rowBytes());
1310ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
1311ce217faddb4b40c1b3e698944da1951027080427Romain Guy    } else {
1312ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
1313ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
1314ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1315ce217faddb4b40c1b3e698944da1951027080427Romain Guy        while (--height >= 0) {
1316ce217faddb4b40c1b3e698944da1951027080427Romain Guy            proc(d, src, width, ctable);
1317ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1318ce217faddb4b40c1b3e698944da1951027080427Romain Guy            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
1319ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
1320ce217faddb4b40c1b3e698944da1951027080427Romain Guy                    SkAlphaType::kUnpremul_SkAlphaType);
1321ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1322ce217faddb4b40c1b3e698944da1951027080427Romain Guy            d += stride;
1323ce217faddb4b40c1b3e698944da1951027080427Romain Guy            src = (void*)((const char*)src + bitmap.rowBytes());
1324ce217faddb4b40c1b3e698944da1951027080427Romain Guy        }
132532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1326ce217faddb4b40c1b3e698944da1951027080427Romain Guy
132732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(pixelArray, dst, 0);
132832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
132932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
133032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
133132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
133232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
133357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint colorHandle) {
1334f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1335c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
133632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor color = static_cast<SkColor>(colorHandle);
1337f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1338f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bitmap.getPixels()) {
133932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
134032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
134132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1342f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    FromColorProc proc = ChooseFromColorProc(bitmap);
134332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
134432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
134532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
134632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1347ce217faddb4b40c1b3e698944da1951027080427Romain Guy    SkColorSpace* colorSpace = bitmap.colorSpace();
1348d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy    if (bitmap.colorType() != kRGBA_F16_SkColorType &&
1349d70532d123b816e0f2ae482258b4e3af56fcdcb2Romain Guy            !GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
1350ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto sRGB = SkColorSpace::MakeSRGB();
1351ce217faddb4b40c1b3e698944da1951027080427Romain Guy        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
1352ce217faddb4b40c1b3e698944da1951027080427Romain Guy        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
1353ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
1354ce217faddb4b40c1b3e698944da1951027080427Romain Guy                SkAlphaType::kUnpremul_SkAlphaType);
1355ce217faddb4b40c1b3e698944da1951027080427Romain Guy    }
1356ce217faddb4b40c1b3e698944da1951027080427Romain Guy
1357f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1358f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap.notifyPixelsChanged();
135932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
136032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
136132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
136232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
136357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1364f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1365c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
136632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1367f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            x, y, width, height, bitmap);
136832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
136932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
137032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
137132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                      jlong bitmapHandle, jobject jbuffer) {
1372f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1373c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1374f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1375f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getPixels();
137632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
137732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != src) {
137832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
137932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
138032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1381f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(abp.pointer(), src, bitmap.getSize());
138232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
138332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
138432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
138532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
138632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                        jlong bitmapHandle, jobject jbuffer) {
1387f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1388c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv    reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
1389f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1390f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* dst = bitmap.getPixels();
139132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
139232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != dst) {
139332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
139432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1395f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(dst, abp.pointer(), bitmap.getSize());
1396f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bitmap.notifyPixelsChanged();
139732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
139832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
139932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1400795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craikstatic jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle, jlong bm1Handle) {
1401f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm0;
1402f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm1;
14031eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
14041eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    LocalScopedBitmap bitmap0(bm0Handle);
14051eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    LocalScopedBitmap bitmap1(bm1Handle);
14061eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
14071eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // Paying the price for making Hardware Bitmap as Config:
14081eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // later check for colorType will pass successfully,
14091eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    // because Hardware Config internally may be RGBA8888 or smth like that.
141015a108550e3d74b406927d85c8e69018761adf49sergeyv    if (bitmap0->isHardware() != bitmap1->isHardware()) {
14111eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv        return JNI_FALSE;
14121eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    }
14131eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv
14141eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    bitmap0->bitmap().getSkBitmap(&bm0);
14151eabed3d14fdc47ac6939cfa98521adcb45bc224sergeyv    bitmap1->bitmap().getSkBitmap(&bm1);
1416795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik    if (bm0.width() != bm1.width()
1417795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.height() != bm1.height()
1418795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.colorType() != bm1.colorType()
1419795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || bm0.alphaType() != bm1.alphaType()
1420795bd0fe93e8bb5214e22cd38aea6a9dc651604bChris Craik            || !SkColorSpace::Equals(bm0.colorSpace(), bm1.colorSpace())) {
142132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
142232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
142332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1424f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp0(bm0);
1425f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp1(bm1);
142632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
142732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // if we can't load the pixels, return false
1428f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
142932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
143032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
143132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1432f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bm0.colorType() == kIndex_8_SkColorType) {
1433f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct0 = bm0.getColorTable();
1434f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct1 = bm1.getColorTable();
143532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (NULL == ct0 || NULL == ct1) {
143632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
143732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
143832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ct0->count() != ct1->count()) {
143932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
144032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
144132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
144232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        const size_t size = ct0->count() * sizeof(SkPMColor);
144371487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
144432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
144532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
144632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
144732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
144832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now compare each scanline. We can't do the entire buffer at once,
144932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // since we don't care about the pixel values that might extend beyond
145032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // the width (since the scanline might be larger than the logical width)
1451f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const int h = bm0.height();
1452f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const size_t size = bm0.width() * bm0.bytesPerPixel();
145332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < h; y++) {
145453001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
145553001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
145653001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
145753001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
145853001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // to warn user those 2 unrecognized config bitmaps may be different.
1459f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm0Addr = bm0.getAddr(0, y);
1460f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm1Addr = bm1.getAddr(0, y);
146153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
146253001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if(bm0Addr == NULL || bm1Addr == NULL) {
146353001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen            return JNI_FALSE;
146453001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        }
146553001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
146653001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
146732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
146832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
146932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
147032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
147132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
147232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
14734387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reckstatic void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
14744387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    LocalScopedBitmap bitmapHandle(bitmapPtr);
14754387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    if (!bitmapHandle.valid()) return;
1476ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmapHandle->bitmap());
14774387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck}
14784387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck
14794508218850faedea95371188da587b6734f5f3dasergeyvstatic jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
14804508218850faedea95371188da587b6734f5f3dasergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
14814508218850faedea95371188da587b6734f5f3dasergeyv    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
14824508218850faedea95371188da587b6734f5f3dasergeyv}
14834508218850faedea95371188da587b6734f5f3dasergeyv
14846e3658a63843096058ed444d073fbcd191fd7e1bsergeyvstatic jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bitmapPtr) {
148581f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
148681f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
148781f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv            "Hardware config is only supported config in Bitmap_nativeCopyPreserveInternalConfig");
148881f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
148981f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    SkBitmap src;
149081f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    hwuiBitmap.getSkBitmap(&src);
149181f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv
149281f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    SkBitmap result;
149381f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    HeapAllocator allocator;
149481f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    if (!src.copyTo(&result, hwuiBitmap.info().colorType(), &allocator)) {
149581f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv        doThrowRE(env, "Could not copy a hardware bitmap.");
149681f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv        return NULL;
149781f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    }
1498656117bed2fc1937bcebd615898924ed57c48979sergeyv    return createBitmap(env, allocator.getStorageObjAndReset(), getPremulBitmapCreateFlags(false));
149981f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv}
150081f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv
15010a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyvstatic jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
15020a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
15030a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
15040a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    if (!bitmap.get()) {
15050a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv        ALOGW("failed to create hardware bitmap from graphic buffer");
15060a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv        return NULL;
15070a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    }
1508656117bed2fc1937bcebd615898924ed57c48979sergeyv    return bitmap::createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
15090a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv}
15100a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv
15116e3658a63843096058ed444d073fbcd191fd7e1bsergeyvstatic jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitmapPtr) {
15126e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
15136e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
15146e3658a63843096058ed444d073fbcd191fd7e1bsergeyv            "Hardware config is only supported config in Bitmap_getGraphicBuffer");
15156e3658a63843096058ed444d073fbcd191fd7e1bsergeyv
15166e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    Bitmap& hwuiBitmap = bitmapHandle->bitmap();
15176e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    sp<GraphicBuffer> buffer(hwuiBitmap.graphicBuffer());
15186e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    return createJavaGraphicBuffer(env, buffer);
15196e3658a63843096058ed444d073fbcd191fd7e1bsergeyv}
15206e3658a63843096058ed444d073fbcd191fd7e1bsergeyv
152132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
1522c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass make_globalref(JNIEnv* env, const char classname[])
1523c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1524c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jclass c = env->FindClass(classname);
1525c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(c);
1526c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return (jclass) env->NewGlobalRef(c);
1527c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
1528c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
1529c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1530c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv                                const char fieldname[], const char type[])
1531c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1532c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jfieldID id = env->GetFieldID(clazz, fieldname, type);
1533c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(id);
1534c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return id;
1535c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
153632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
153776f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gBitmapMethods[] = {
153832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
153932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_creator },
154032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
154132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_copy },
1542721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1543721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        (void*)Bitmap_copyAshmem },
1544a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1545a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson        (void*)Bitmap_copyAshmemConfig },
1546775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
154732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
15484508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
154932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
155032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_compress },
155132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
155232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
155332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
155432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
155557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
155657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
155757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
155832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
155932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
156032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreateFromParcel",
156132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
156232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_createFromParcel },
156332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
156432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_writeToParcel },
156532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
156632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_extractAlpha },
156732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
156857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
156957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
157057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
157157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
157232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
157332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsToBuffer },
157432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
157532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsFromBuffer },
157632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
15774387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
15784508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
157981f97ee47ccf0d011cdc4f38b6ea5c45b70dedc0sergeyv    {   "nativeCopyPreserveInternalConfig", "(J)Landroid/graphics/Bitmap;",
15806e3658a63843096058ed444d073fbcd191fd7e1bsergeyv        (void*)Bitmap_copyPreserveInternalConfig },
15810a0f23163a7a62900d46c7f81d109320d73d6c6bsergeyv    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
15826e3658a63843096058ed444d073fbcd191fd7e1bsergeyv        (void*) Bitmap_createHardwareBitmap },
15836e3658a63843096058ed444d073fbcd191fd7e1bsergeyv    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
1584efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy        (void*) Bitmap_createGraphicBufferHandle },
1585efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    {   "nativeGetColorSpace",      "(J[F[F)Z", (void*)Bitmap_getColorSpace },
1586efb4b06493fe7b1604c762a448b13c7af2845a8dRomain Guy    {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
158732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
158832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
158932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikint register_android_graphics_Bitmap(JNIEnv* env)
159032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik{
1591c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1592c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1593c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1594c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1595c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
1596ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1597ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                         NELEM(gBitmapMethods));
15989192d5e8d78b826a665ce048c007e6eaf0f5b003John Reck}
1599