Bitmap.cpp revision c69853c8b72540e5031d28e03cbce5a390c6959f
1f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#define LOG_TAG "Bitmap"
2f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#include "Bitmap.h"
3f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkBitmap.h"
532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkPixelRef.h"
632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkImageEncoder.h"
757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III#include "SkImageInfo.h"
832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkColorPriv.h"
932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "GraphicsJNI.h"
1032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkDither.h"
1132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkUnPreMultiply.h"
1232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "SkStream.h"
1332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <binder/Parcel.h>
1532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_os_Parcel.h"
1632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_util_Binder.h"
1732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "android_nio_utils.h"
1832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include "CreateJavaOutputStreamAdaptor.h"
19f29ed28c7b878ef28058bc730715d0d32445bc57John Reck#include <Caches.h>
20dccca44ffda4836b56a21da95a046c9708ffd49csergeyv#include <hwui/Paint.h>
214387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck#include <renderthread/RenderProxy.h>
2232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
23ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe#include "core_jni_helpers.h"
24ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe
2532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik#include <jni.h>
2639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <memory>
2739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <string>
2839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <sys/mman.h>
2939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews#include <cutils/ashmem.h>
3032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
31a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#define DEBUG_PARCEL 0
328cee7c17119b204be88860feb812f2374d0de732Riley Andrews#define ASHMEM_BITMAP_MIN_SIZE (128 * (1 << 10))
33a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
34c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass   gBitmap_class;
35c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID gBitmap_nativePtr;
36c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_constructorMethodID;
37c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_reinitMethodID;
38c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jmethodID gBitmap_getAllocationByteCountMethodID;
39c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
40f29ed28c7b878ef28058bc730715d0d32445bc57John Recknamespace android {
41f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
42c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvclass Bitmap {
43f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
44c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    Bitmap(PixelRef* pixelRef)
45c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        : mPixelRef(pixelRef) { }
46c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
47c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void freePixels() {
48c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mInfo = mPixelRef->info();
49c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mHasHardwareMipMap = mPixelRef->hasHardwareMipMap();
50c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mAllocationSize = mPixelRef->getAllocationByteCount();
51c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mRowBytes = mPixelRef->rowBytes();
52c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mGenerationId = mPixelRef->getGenerationID();
53c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mPixelRef.reset();
54f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
55f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
56c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool valid() {
57c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return !!mPixelRef;
58f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
59f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
60c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    PixelRef* pixelRef() { return mPixelRef.get(); }
61c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
62c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void assertValid() {
63c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        LOG_ALWAYS_FATAL_IF(!valid(), "Error, cannot access an invalid/free'd bitmap here!");
64c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
65c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
66c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void getSkBitmap(SkBitmap* outBitmap) {
67c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
68c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mPixelRef->getSkBitmap(outBitmap);
69c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
700781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
71c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool hasHardwareMipMap() {
72c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        if (mPixelRef) {
73c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            return mPixelRef->hasHardwareMipMap();
74c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
75f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mHasHardwareMipMap;
76f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
77f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
78f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void setHasHardwareMipMap(bool hasMipMap) {
79c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
80c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mPixelRef->setHasHardwareMipMap(hasMipMap);
81f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
82f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
83c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    void setAlphaType(SkAlphaType alphaType) {
84c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        assertValid();
85c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mPixelRef->setAlphaType(alphaType);
86f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
87f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
88c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    const SkImageInfo& info() {
89c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        if (mPixelRef) {
90c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            return mPixelRef->info();
91c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
92c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mInfo;
93f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
94f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
95c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t getAllocationByteCount() const {
96c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        if (mPixelRef) {
97c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            return mPixelRef->getAllocationByteCount();
98c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
99c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mAllocationSize;
100f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
101f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
102c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t rowBytes() const {
103c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        if (mPixelRef) {
104c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            return mPixelRef->rowBytes();
105c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
106c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mRowBytes;
107c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
108f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
109c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t getGenerationID() const {
110c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        if (mPixelRef) {
111c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            return mPixelRef->getGenerationID();
112c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        }
113c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mGenerationId;
114f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
115c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
116c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    ~Bitmap() { }
117c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
118c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvprivate:
119c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    sk_sp<PixelRef> mPixelRef;
120c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkImageInfo mInfo;
121c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool mHasHardwareMipMap;
122c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mAllocationSize;
123c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    size_t mRowBytes;
124c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    uint32_t mGenerationId;
125f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
126f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
127c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid PixelRef::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
128c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (kIndex_8_SkColorType != newInfo.colorType()) {
129c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        ctable = nullptr;
130c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
131c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    mRowBytes = rowBytes;
132c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (mColorTable.get() != ctable) {
133c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        mColorTable.reset(ctable);
134c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
135c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
136c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // Need to validate the alpha type to filter against the color type
137c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // to prevent things like a non-opaque RGB565 bitmap
138c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkAlphaType alphaType;
139c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LOG_ALWAYS_FATAL_IF(!SkColorTypeValidateAlphaType(
140c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            newInfo.colorType(), newInfo.alphaType(), &alphaType),
141c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            "Failed to validate alpha type!");
142c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
143c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // Dirty hack is dirty
144c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // TODO: Figure something out here, Skia's current design makes this
145c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // really hard to work with. Skia really, really wants immutable objects,
146c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // but with the nested-ref-count hackery going on that's just not
147c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // feasible without going insane trying to figure it out
148c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
149c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    *myInfo = newInfo;
150c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    changeAlphaType(alphaType);
151c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
152c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // Docs say to only call this in the ctor, but we're going to call
153c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // it anyway even if this isn't always the ctor.
154c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // TODO: Fix this too as part of the above TODO
155c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    setPreLocked(getStorage(), mRowBytes, mColorTable.get());
156c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
157c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
158c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvPixelRef::PixelRef(void* address, size_t size, const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
159c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            : SkPixelRef(info)
160c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            , mPixelStorageType(PixelStorageType::Heap) {
1614508218850faedea95371188da587b6734f5f3dasergeyv    mPixelStorage.heap.address = address;
1624508218850faedea95371188da587b6734f5f3dasergeyv    mPixelStorage.heap.size = size;
163c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    reconfigure(info, rowBytes, ctable);
164f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
165f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
166c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvPixelRef::PixelRef(void* address, void* context, FreeFunc freeFunc,
167c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv                const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
168c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            : SkPixelRef(info)
169c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            , mPixelStorageType(PixelStorageType::External) {
170f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.external.address = address;
171f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.external.context = context;
172f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    mPixelStorage.external.freeFunc = freeFunc;
173c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    reconfigure(info, rowBytes, ctable);
174f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
175f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
176c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvPixelRef::PixelRef(void* address, int fd, size_t mappedSize,
177c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv                const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable)
178c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            : SkPixelRef(info)
179c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            , mPixelStorageType(PixelStorageType::Ashmem) {
18039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    mPixelStorage.ashmem.address = address;
18139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    mPixelStorage.ashmem.fd = fd;
182003bdee0b6680b8ab0d1fa07451e50e8c3555160John Reck    mPixelStorage.ashmem.size = mappedSize;
183c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    reconfigure(info, rowBytes, ctable);
184f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
185f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
186c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvPixelRef::~PixelRef() {
187f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    switch (mPixelStorageType) {
188f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    case PixelStorageType::External:
189f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        mPixelStorage.external.freeFunc(mPixelStorage.external.address,
190f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                mPixelStorage.external.context);
191f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
19239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    case PixelStorageType::Ashmem:
19339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        munmap(mPixelStorage.ashmem.address, mPixelStorage.ashmem.size);
19439d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        close(mPixelStorage.ashmem.fd);
19539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        break;
1964508218850faedea95371188da587b6734f5f3dasergeyv    case PixelStorageType::Heap:
1974508218850faedea95371188da587b6734f5f3dasergeyv        free(mPixelStorage.heap.address);
198f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        break;
199f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
200f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
201f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (android::uirenderer::Caches::hasInstance()) {
202c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        android::uirenderer::Caches::getInstance().textureCache.releaseTexture(getStableID());
203f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
204f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
205f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
206c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvbool PixelRef::hasHardwareMipMap() const {
207c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return mHasHardwareMipMap;
208f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
209f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
210c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid PixelRef::setHasHardwareMipMap(bool hasMipMap) {
211c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    mHasHardwareMipMap = hasMipMap;
212f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
213f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
214c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid* PixelRef::getStorage() const {
215c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    switch (mPixelStorageType) {
216c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    case PixelStorageType::External:
217c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mPixelStorage.external.address;
218c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    case PixelStorageType::Ashmem:
219c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mPixelStorage.ashmem.address;
220c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    case PixelStorageType::Heap:
221c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mPixelStorage.heap.address;
222c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
223c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
224c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
225c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvbool PixelRef::onNewLockPixels(LockRec* rec) {
226c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    rec->fPixels = getStorage();
227c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    rec->fRowBytes = mRowBytes;
228c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    rec->fColorTable = mColorTable.get();
229c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return true;
230c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
231c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
232c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvsize_t PixelRef::getAllocatedSizeInBytes() const {
233c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return info().getSafeSize(mRowBytes);
234c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
235c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
236c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvint PixelRef::getAshmemFd() const {
23739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    switch (mPixelStorageType) {
23839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    case PixelStorageType::Ashmem:
23939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        return mPixelStorage.ashmem.fd;
24039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    default:
24139d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        return -1;
24239d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
24339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews}
24439d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
245c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvsize_t PixelRef::getAllocationByteCount() const {
2464508218850faedea95371188da587b6734f5f3dasergeyv    switch (mPixelStorageType) {
2474508218850faedea95371188da587b6734f5f3dasergeyv    case PixelStorageType::Heap:
2484508218850faedea95371188da587b6734f5f3dasergeyv        return mPixelStorage.heap.size;
2494508218850faedea95371188da587b6734f5f3dasergeyv    default:
2504508218850faedea95371188da587b6734f5f3dasergeyv        return rowBytes() * height();
2514508218850faedea95371188da587b6734f5f3dasergeyv    }
2524508218850faedea95371188da587b6734f5f3dasergeyv}
2534508218850faedea95371188da587b6734f5f3dasergeyv
254c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid PixelRef::reconfigure(const SkImageInfo& info) {
2552a94a10bec186d832c2b95675cb6dc27b012c2d0Derek Sollenberger    reconfigure(info, info.minRowBytes(), nullptr);
256f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
257f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
258c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid PixelRef::setAlphaType(SkAlphaType alphaType) {
2590781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck    if (!SkColorTypeValidateAlphaType(info().colorType(), alphaType, &alphaType)) {
2600781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        return;
2610781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck    }
2620781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck
263c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    changeAlphaType(alphaType);
264f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
265f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
266c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid PixelRef::getSkBitmap(SkBitmap* outBitmap) {
267c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    outBitmap->setInfo(info(), rowBytes());
268c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    outBitmap->setPixelRef(this);
269c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
270f29ed28c7b878ef28058bc730715d0d32445bc57John Reck}
271f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
272f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
273f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// Convenience class that does not take a global ref on the pixels, relying
274f29ed28c7b878ef28058bc730715d0d32445bc57John Reck// on the caller already having a local JNI ref
275f29ed28c7b878ef28058bc730715d0d32445bc57John Reckclass LocalScopedBitmap {
276f29ed28c7b878ef28058bc730715d0d32445bc57John Reckpublic:
277c6baf563ba6aa207a48317c177b29f1d2b70cf3dChih-Hung Hsieh    explicit LocalScopedBitmap(jlong bitmapHandle)
278f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            : mBitmap(reinterpret_cast<Bitmap*>(bitmapHandle)) {}
279f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
280f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    Bitmap* operator->() {
281f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mBitmap;
282f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
283f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
284f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* pixels() {
285c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        return mBitmap->pixelRef()->pixels();
286f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
287f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
288f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool valid() {
289f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return mBitmap && mBitmap->valid();
290f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
291f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
292f29ed28c7b878ef28058bc730715d0d32445bc57John Reckprivate:
293f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    Bitmap* mBitmap;
294f29ed28c7b878ef28058bc730715d0d32445bc57John Reck};
295f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
296c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvnamespace bitmap {
297c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
298c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv// Assert that bitmap's SkAlphaType is consistent with isPremultiplied.
299c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) {
300c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is
301c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // irrelevant. This just tests to ensure that the SkAlphaType is not
302c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // opposite of isPremultiplied.
303c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isPremultiplied) {
304c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kUnpremul_SkAlphaType);
305c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    } else {
306c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        SkASSERT(info.alphaType() != kPremul_SkAlphaType);
307c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
308c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
309c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
310c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
311c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        bool isPremultiplied)
312c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
313c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
314c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
315c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    assert_premultiplied(info, isPremultiplied);
316c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
317c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    env->CallVoidMethod(javaBitmap, gBitmap_reinitMethodID,
318c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            info.width(), info.height(), isPremultiplied);
319c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
320c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
321c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvint getBitmapAllocationByteCount(JNIEnv* env, jobject javaBitmap)
322c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
323c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return env->CallIntMethod(javaBitmap, gBitmap_getAllocationByteCountMethodID);
324c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
325c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
326c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvjobject createBitmap(JNIEnv* env, PixelRef* pixelRef,
327c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
328c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        int density) {
329c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
330c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
331c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // The caller needs to have already set the alpha type properly, so the
332c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    // native SkBitmap stays in sync with the Java Bitmap.
333c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    assert_premultiplied(pixelRef->info(), isPremultiplied);
334c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    Bitmap* bitmap = new Bitmap(pixelRef);
335c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
336c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            reinterpret_cast<jlong>(bitmap), pixelRef->width(), pixelRef->height(), density, isMutable,
337c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv            isPremultiplied, ninePatchChunk, ninePatchInsets);
338c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
339c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (env->ExceptionCheck() != 0) {
340c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        ALOGE("*** Uncaught exception returned from Java call!\n");
341c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv        env->ExceptionDescribe();
342c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    }
343c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return obj;
344c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
345c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
346c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvvoid toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
347c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap bitmap(bitmapHandle);
348c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->getSkBitmap(outBitmap);
349c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
350c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
351c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvPixelRef* toPixelRef(JNIEnv* env, jobject bitmap) {
352c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env);
353c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(bitmap);
354c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
355c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
356c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    LocalScopedBitmap localBitmap(bitmapHandle);
357c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    localBitmap->assertValid();
358c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return localBitmap->pixelRef();
359c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
360c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
361c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace bitmap
362c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
363c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv} // namespace android
364c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
365c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android;
366c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvusing namespace android::bitmap;
367c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
36832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
36932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// Conversions to/from SkColor, for get/setPixels, and the create method, which
37032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// is basically like setPixels
37132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37232054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
37332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              int x, int y);
37432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32(void* dst, const SkColor src[], int width,
37632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
37732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
37832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
37932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
38032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPreMultiplyColor(*src++);
38132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
38232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
38332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
38432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
38532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                          int, int) {
38646d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    // Needed to thwart the unreachable code detection from clang.
38746d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
38846d8444631b4b1253a76bfcc78a29d26014d022fDan Albert
38932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // SkColor's ordering may be different from SkPMColor
39046d8444631b4b1253a76bfcc78a29d26014d022fDan Albert    if (sk_color_ne_zero) {
39132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        memcpy(dst, src, width * sizeof(SkColor));
39232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
39332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
39432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
39532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // order isn't same, repack each pixel manually
39632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor* d = (SkPMColor*)dst;
39732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int i = 0; i < width; i++) {
39832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
39932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
40032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   SkColorGetG(c), SkColorGetB(c));
40132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
40232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
40332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
40432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D565(void* dst, const SkColor src[], int width,
40532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           int x, int y) {
40632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    uint16_t* d = (uint16_t*)dst;
40732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
40832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_565_SCAN(y);
40932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
41032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
41132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
41232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                DITHER_VALUE(x));
41332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
41432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
41532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
41632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444(void* dst, const SkColor src[], int width,
41732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
41832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
41932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
42032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
42132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
42232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPreMultiplyColor(*src++);
42332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
42432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
42532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
42632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
42732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
42832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
42932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            int x, int y) {
43032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkPMColor16* d = (SkPMColor16*)dst;
43132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    DITHER_4444_SCAN(y);
43332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int stop = x + width; x < stop; x++) {
43432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkColor c = *src++;
43532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
43632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
43732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
43832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            SkColorGetG(c), SkColorGetB(c));
43932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
44032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//        *d++ = SkPixel32ToPixel4444(pmc);
44132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
44232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
44332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
4446260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
4456260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    uint8_t* d = (uint8_t*)dst;
4466260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
4476260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    for (int stop = x + width; x < stop; x++) {
4486260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *d++ = SkColorGetA(*src++);
4496260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    }
4506260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
4516260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
45232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
45357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
45457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    switch (bitmap.colorType()) {
45557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kN32_SkColorType:
45657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
45757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kARGB_4444_SkColorType:
45857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
45957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    FromColor_D4444_Raw;
46057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        case kRGB_565_SkColorType:
46132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return FromColor_D565;
4626260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
4636260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return FromColor_DA8;
46432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
46532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
46632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
46732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
46832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
46932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
47032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikbool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
47157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
47232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkAutoLockPixels alp(dstBitmap);
47332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    void* dst = dstBitmap.getPixels();
47457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    FromColorProc proc = ChooseFromColorProc(dstBitmap);
47532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
47632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == dst || NULL == proc) {
47732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return false;
47832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
47932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
48032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const jint* array = env->GetIntArrayElements(srcColors, NULL);
48132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkColor* src = (const SkColor*)array + srcOffset;
48232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
48332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // reset to to actual choice from caller
48432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dst = dstBitmap.getAddr(x, y);
48532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now copy/convert each scanline
48632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < height; y++) {
48732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        proc(dst, src, width, x, y);
48832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        src += srcStride;
48932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        dst = (char*)dst + dstBitmap.rowBytes();
49032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
49132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
49232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    dstBitmap.notifyPixelsChanged();
49332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
49432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
49532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 JNI_ABORT);
49632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return true;
49732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
49832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
49932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik//////////////////// ToColor procs
50032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
50132054b0b3edb350a5444c47753b2982312dd7ffdChris Craiktypedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
50232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                            SkColorTable*);
50332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
50432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
50532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
50632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
50732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
50832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
50932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
51032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
51132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
51232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
51332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Raw(SkColor dst[], const void* src, int width,
51432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable*) {
51532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
51632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
51732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
51832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
51932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
52032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
52132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
52232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
52332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
52432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S32_Opaque(SkColor dst[], const void* src, int width,
52532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable*) {
52632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
52732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor* s = (const SkPMColor*)src;
52832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
52932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = *s++;
53032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
53132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
53232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
53332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
53432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
53532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width,
53632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
53732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
53832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
53932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
54032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
54132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
54232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
54332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
54432054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Raw(SkColor dst[], const void* src, int width,
54532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkColorTable*) {
54632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
54732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
54832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
54932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
55032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
55132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
55232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
55332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
55432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
55532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width,
55632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                 SkColorTable*) {
55732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
55832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const SkPMColor16* s = (const SkPMColor16*)src;
55932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
56032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = SkPixel4444ToPixel32(*s++);
56132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
56232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
56332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
56432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
56532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
56632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_S565(SkColor dst[], const void* src, int width,
56732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                         SkColorTable*) {
56832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
56932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint16_t* s = (const uint16_t*)src;
57032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
57132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        uint16_t c = *s++;
57232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
57332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkPacked16ToB32(c));
57432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
57532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
57632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
57732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Alpha(SkColor dst[], const void* src, int width,
57832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
57932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
58032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
58171487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
58232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
58332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkUnPreMultiply::PMColorToColor(colors[*s++]);
58432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
58532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
58632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
58732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Raw(SkColor dst[], const void* src, int width,
58832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              SkColorTable* ctable) {
58932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
59032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
59171487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
59232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
59332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
59432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
59532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                SkGetPackedG32(c), SkGetPackedB32(c));
59632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
59732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
59832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
59932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void ToColor_SI8_Opaque(SkColor dst[], const void* src, int width,
60032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkColorTable* ctable) {
60132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkASSERT(width > 0);
60232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    const uint8_t* s = (const uint8_t*)src;
60371487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed    const SkPMColor* colors = ctable->readColors();
60432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    do {
60532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkPMColor c = colors[*s++];
60632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
60732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                               SkGetPackedB32(c));
60832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } while (--width != 0);
60932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
61032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
6116260b22501996d2e7a0323b493ae6c4badb93c28Chris Craikstatic void ToColor_SA8(SkColor dst[], const void* src, int width, SkColorTable*) {
6126260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    SkASSERT(width > 0);
6136260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    const uint8_t* s = (const uint8_t*)src;
6146260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    do {
6156260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        uint8_t c = *s++;
6166260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        *dst++ = SkColorSetARGB(c, c, c, c);
6176260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik    } while (--width != 0);
6186260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik}
6196260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik
62032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// can return NULL
62157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic ToColorProc ChooseToColorProc(const SkBitmap& src) {
622b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    switch (src.colorType()) {
623b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kN32_SkColorType:
62457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
62557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
62657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Opaque;
62757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
62857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Alpha;
62957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
63057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S32_Raw;
63157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
63257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
63357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
634b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kARGB_4444_SkColorType:
63557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
63657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
63757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Opaque;
63857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
63957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Alpha;
64057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
64157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_S4444_Raw;
64257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
64357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
64457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
645b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kRGB_565_SkColorType:
64632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return ToColor_S565;
647b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        case kIndex_8_SkColorType:
64832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            if (src.getColorTable() == NULL) {
64932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                return NULL;
65032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            }
65157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            switch (src.alphaType()) {
65257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kOpaque_SkAlphaType:
65357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Opaque;
65457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kPremul_SkAlphaType:
65557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Alpha;
65657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                case kUnpremul_SkAlphaType:
65757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return ToColor_SI8_Raw;
65857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                default:
65957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                    return NULL;
66057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III            }
6616260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik        case kAlpha_8_SkColorType:
6626260b22501996d2e7a0323b493ae6c4badb93c28Chris Craik            return ToColor_SA8;
66332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        default:
66432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            break;
66532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
66632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return NULL;
66732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
66832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
66932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
67032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
67132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
67232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic int getPremulBitmapCreateFlags(bool isMutable) {
673c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    int flags = android::bitmap::kBitmapCreateFlag_Premultiplied;
674c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    if (isMutable) flags |= android::bitmap::kBitmapCreateFlag_Mutable;
67532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return flags;
67632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
67732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
67832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
67932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint offset, jint stride, jint width, jint height,
68032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jint configHandle, jboolean isMutable) {
6811103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
68232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != jColors) {
68332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        size_t n = env->GetArrayLength(jColors);
68432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (n < SkAbs32(stride) * (size_t)height) {
68532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            doThrowAIOOBE(env);
68632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return NULL;
68732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
68832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
68932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // ARGB_4444 is a deprecated format, convert automatically to 8888
691b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kARGB_4444_SkColorType) {
692b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        colorType = kN32_SkColorType;
69332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
69432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
69532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkBitmap bitmap;
696b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));
69732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
698c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    PixelRef* nativeBitmap = GraphicsJNI::allocateHeapPixelRef(&bitmap, NULL);
699f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!nativeBitmap) {
70032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
70132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
70232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
70332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (jColors != NULL) {
70432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        GraphicsJNI::SetPixels(env, jColors, offset, stride,
70557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III                0, 0, width, height, bitmap);
70632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
70732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
708c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, nativeBitmap,
709f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(isMutable));
71032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
71132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
71232054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle,
71332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                           jint dstConfigHandle, jboolean isMutable) {
714f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
715f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
7161103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
7174508218850faedea95371188da587b6734f5f3dasergeyv    SkBitmap result;
7184508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
71932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
720f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!src.copyTo(&result, dstCT, &allocator)) {
72132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
72232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
723c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    auto pixelRef = allocator.getStorageObjAndReset();
724c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, pixelRef, getPremulBitmapCreateFlags(isMutable));
72532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
72632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
727c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic PixelRef* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& dstCT) {
728721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    SkBitmap result;
729721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
730721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    AshmemPixelAllocator allocator(env);
731a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    if (!src.copyTo(&result, dstCT, &allocator)) {
732721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        return NULL;
733721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    }
734c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    auto pixelRef = allocator.getStorageObjAndReset();
735c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    pixelRef->setImmutable();
736c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return pixelRef;
737a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
738a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
739a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) {
740a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
741a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
742a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = src.colorType();
743c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    auto pixelRef = Bitmap_copyAshmemImpl(env, src, dstCT);
744c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jobject ret = createBitmap(env, pixelRef, getPremulBitmapCreateFlags(false));
745a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    return ret;
746a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson}
747a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson
748a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winsonstatic jobject Bitmap_copyAshmemConfig(JNIEnv* env, jobject, jlong srcHandle, jint dstConfigHandle) {
749a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkBitmap src;
750a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
751a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    SkColorType dstCT = GraphicsJNI::legacyBitmapConfigToColorType(dstConfigHandle);
752c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    auto pixelRef = Bitmap_copyAshmemImpl(env, src, dstCT);
753c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jobject ret = createBitmap(env, pixelRef, getPremulBitmapCreateFlags(false));
754721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    return ret;
755721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews}
756721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews
757775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic void Bitmap_destruct(Bitmap* bitmap) {
758c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    delete bitmap;
75932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
76032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
761775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhlerstatic jlong Bitmap_getNativeFinalizer(JNIEnv*, jobject) {
762775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Bitmap_destruct));
763775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler}
764775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler
76532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_recycle(JNIEnv* env, jobject, jlong bitmapHandle) {
766f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
767f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->freePixels();
76832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
76932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
77032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
77132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_reconfigure(JNIEnv* env, jobject clazz, jlong bitmapHandle,
7724508218850faedea95371188da587b6734f5f3dasergeyv        jint width, jint height, jint configHandle, jboolean requestPremul) {
773f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
774c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->assertValid();
7751103b3255945d2eb2fa9c191e84e2270b343cca9Mike Reed    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
77617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III
77717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    // ARGB_4444 is a deprecated format, convert automatically to 8888
77817a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    if (colorType == kARGB_4444_SkColorType) {
77917a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        colorType = kN32_SkColorType;
78017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
7814508218850faedea95371188da587b6734f5f3dasergeyv    size_t requestedSize = width * height * SkColorTypeBytesPerPixel(colorType);
7824508218850faedea95371188da587b6734f5f3dasergeyv    if (requestedSize > bitmap->getAllocationByteCount()) {
78332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // done in native as there's no way to get BytesPerPixel in Java
78432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowIAE(env, "Bitmap not large enough to support new configuration");
78532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
78632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
78717a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    SkAlphaType alphaType;
788f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().colorType() != kRGB_565_SkColorType
789f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            && bitmap->info().alphaType() == kOpaque_SkAlphaType) {
79017a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // If the original bitmap was set to opaque, keep that setting, unless it
79117a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // was 565, which is required to be opaque.
79217a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = kOpaque_SkAlphaType;
79317a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    } else {
79417a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        // Otherwise respect the premultiplied request.
79517a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III        alphaType = requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType;
79617a8bfc38a565ae96f43d36b223779be840bb50cLeon Scroggins III    }
797c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    bitmap->pixelRef()->reconfigure(SkImageInfo::Make(width, height, colorType, alphaType));
79832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
79932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
80032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik// These must match the int values in Bitmap.java
80132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikenum JavaEncodeFormat {
80232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kJPEG_JavaEncodeFormat = 0,
80332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kPNG_JavaEncodeFormat = 1,
80432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    kWEBP_JavaEncodeFormat = 2
80532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
80632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
80732054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_compress(JNIEnv* env, jobject clazz, jlong bitmapHandle,
80832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jint format, jint quality,
80932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jobject jstream, jbyteArray jstorage) {
810f29ed28c7b878ef28058bc730715d0d32445bc57John Reck
811f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
81232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkImageEncoder::Type fm;
81332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
81432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    switch (format) {
81532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kJPEG_JavaEncodeFormat:
81632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kJPEG_Type;
81732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
81832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kPNG_JavaEncodeFormat:
81932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kPNG_Type;
82032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
82132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    case kWEBP_JavaEncodeFormat:
82232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        fm = SkImageEncoder::kWEBP_Type;
82332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        break;
82432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    default:
82532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
82632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
82732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
828f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap.valid()) {
829f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
830f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
83132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
832f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bool success = false;
83332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
834f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkWStream> strm(CreateJavaOutputStreamAdaptor(env, jstream, jstorage));
835f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!strm.get()) {
836f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        return JNI_FALSE;
837f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    }
83832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
839f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    std::unique_ptr<SkImageEncoder> encoder(SkImageEncoder::Create(fm));
840f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (encoder.get()) {
841f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkBitmap skbitmap;
842f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bitmap->getSkBitmap(&skbitmap);
843f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        success = encoder->encodeStream(strm.get(), skbitmap, quality);
84432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
84532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return success ? JNI_TRUE : JNI_FALSE;
84632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
84732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
84832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
849f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
850f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap skBitmap;
851f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap->getSkBitmap(&skBitmap);
852f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    skBitmap.eraseColor(color);
85332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
85432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
85532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_rowBytes(JNIEnv* env, jobject, jlong bitmapHandle) {
856f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
85732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(bitmap->rowBytes());
85832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
85932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
86032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_config(JNIEnv* env, jobject, jlong bitmapHandle) {
861f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
862f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return GraphicsJNI::colorTypeToLegacyBitmapConfig(bitmap->info().colorType());
86332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
86432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
86532054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
866f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
867c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return static_cast<jint>(bitmap->getGenerationID());
86832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
86932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
87057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
871f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
872f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
87357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        return JNI_TRUE;
87457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
87557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    return JNI_FALSE;
87657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
87757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
87832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasAlpha(JNIEnv* env, jobject, jlong bitmapHandle) {
879f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
880f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    return !bitmap->info().isOpaque() ? JNI_TRUE : JNI_FALSE;
88132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
88232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
88357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setHasAlpha(JNIEnv* env, jobject, jlong bitmapHandle,
88457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean hasAlpha, jboolean requestPremul) {
885f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
88657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    if (hasAlpha) {
8870781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(
888f29ed28c7b878ef28058bc730715d0d32445bc57John Reck                requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
88932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    } else {
8900781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck        bitmap->setAlphaType(kOpaque_SkAlphaType);
89157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    }
89257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III}
89357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III
89457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins IIIstatic void Bitmap_setPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle,
89557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jboolean isPremul) {
896f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
897f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (!bitmap->info().isOpaque()) {
89857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        if (isPremul) {
8990781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kPremul_SkAlphaType);
90057ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        } else {
9010781a2f116be045ff1a3aca721c47f9fef980beaJohn Reck            bitmap->setAlphaType(kUnpremul_SkAlphaType);
90257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        }
90332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
90432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
90532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
90632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_hasMipMap(JNIEnv* env, jobject, jlong bitmapHandle) {
907f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
90832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return bitmap->hasHardwareMipMap() ? JNI_TRUE : JNI_FALSE;
90932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
91032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
91132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle,
91232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                jboolean hasMipMap) {
913f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
91432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    bitmap->setHasHardwareMipMap(hasMipMap);
91532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
91632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
91732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
91832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
91932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
92032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
92132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("-------- unparcel parcel is NULL\n");
92232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
92332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
92432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
92532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
92632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
927b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const bool        isMutable = p->readInt32() != 0;
928b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkColorType colorType = (SkColorType)p->readInt32();
929b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const SkAlphaType alphaType = (SkAlphaType)p->readInt32();
930b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         width = p->readInt32();
931b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         height = p->readInt32();
932b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         rowBytes = p->readInt32();
933b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    const int         density = p->readInt32();
934b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed
935b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (kN32_SkColorType != colorType &&
936b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kRGB_565_SkColorType != colorType &&
937b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kARGB_4444_SkColorType != colorType &&
938b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kIndex_8_SkColorType != colorType &&
939b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed            kAlpha_8_SkColorType != colorType) {
940b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed        SkDebugf("Bitmap_createFromParcel unknown colortype: %d\n", colorType);
94132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
94232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
94332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
944ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
94532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
946ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType), rowBytes)) {
947ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        return NULL;
948ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III    }
94932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
95032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColorTable* ctable = NULL;
951b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed    if (colorType == kIndex_8_SkColorType) {
95232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int count = p->readInt32();
953ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        if (count < 0 || count > 256) {
954ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // The data is corrupt, since SkColorTable enforces a value between 0 and 256,
955ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            // inclusive.
956ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            return NULL;
957ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III        }
95832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (count > 0) {
95932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            size_t size = count * sizeof(SkPMColor);
96032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            const SkPMColor* src = (const SkPMColor*)p->readInplace(size);
961ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            if (src == NULL) {
962ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III                return NULL;
963ec419e0b731d2aa32f7f570e4021fe18b8be228dLeon Scroggins III            }
96432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            ctable = new SkColorTable(src, count);
96532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
96632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
96732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
968a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Read the bitmap blob.
969a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap->getSize();
970a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::ReadableBlob blob;
971a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status = p->readBlob(size, &blob);
972a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
97332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkSafeUnref(ctable);
974a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not read bitmap blob.");
97532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
97632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
97732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
978a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Map the bitmap in place from the ashmem region if possible otherwise copy.
979c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    PixelRef* nativeBitmap;
9808cee7c17119b204be88860feb812f2374d0de732Riley Andrews    if (blob.fd() >= 0 && (blob.isMutable() || !isMutable) && (size >= ASHMEM_BITMAP_MIN_SIZE)) {
981a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
982a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.createFromParcel: mapped contents of %s bitmap from %s blob "
983a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "(fds %s)",
984a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                isMutable ? "mutable" : "immutable",
985a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                blob.isMutable() ? "mutable" : "immutable",
986a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
987a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
988a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Dup the file descriptor so we can keep a reference to it after the Parcel
989a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // is disposed.
990a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        int dupFd = dup(blob.fd());
991a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (dupFd < 0) {
992211abad3b92b70dd094949c79f67e686c940fa0cErik Wolsheimer            ALOGE("Error allocating dup fd. Error:%d", errno);
993a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
994a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            SkSafeUnref(ctable);
995a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate dup blob fd.");
996a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
99739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
998a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
999a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Map the pixels in place and take ownership of the ashmem region.
1000a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        nativeBitmap = GraphicsJNI::mapAshmemPixelRef(env, bitmap.get(),
1001003bdee0b6680b8ab0d1fa07451e50e8c3555160John Reck                ctable, dupFd, const_cast<void*>(blob.data()), size, !isMutable);
1002a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
1003a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
1004a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            close(dupFd);
1005a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1006a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate ashmem pixel ref.");
1007a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
100839d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1009a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1010a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Clear the blob handle, don't release it.
1011a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.clear();
1012a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
1013a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1014a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (blob.fd() >= 0) {
1015a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents of mutable bitmap "
1016a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "from immutable blob (fds %s)",
1017a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
1018a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        } else {
1019a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            ALOGD("Bitmap.createFromParcel: copied contents from %s blob "
1020a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    "(fds %s)",
1021a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    blob.isMutable() ? "mutable" : "immutable",
1022a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                    p->allowFds() ? "allowed" : "forbidden");
102339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1024a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1025a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1026a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Copy the pixels into a new buffer.
10274508218850faedea95371188da587b6734f5f3dasergeyv        nativeBitmap = GraphicsJNI::allocateHeapPixelRef(bitmap.get(), ctable);
1028a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        SkSafeUnref(ctable);
1029a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (!nativeBitmap) {
1030a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            blob.release();
1031a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not allocate java pixel ref.");
1032a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            return NULL;
103339d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1034a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->lockPixels();
1035a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(bitmap->getPixels(), blob.data(), size);
1036a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        bitmap->unlockPixels();
1037a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1038a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        // Release the blob handle.
1039a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        blob.release();
104039d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
1041a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1042c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, nativeBitmap,
1043a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            getPremulBitmapCreateFlags(isMutable), NULL, NULL, density);
1044a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown}
104539d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
104632054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
104732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jlong bitmapHandle,
104832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jboolean isMutable, jint density,
104932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                     jobject parcel) {
105032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (parcel == NULL) {
105132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        SkDebugf("------- writeToParcel null parcel\n");
105232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
105332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
105432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
105532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    android::Parcel* p = android::parcelForJavaObject(env, parcel);
1056f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
105739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews
1058c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    auto androidBitmap = reinterpret_cast<Bitmap*>(bitmapHandle);
105939d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    androidBitmap->getSkBitmap(&bitmap);
106032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
106132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(isMutable);
1062f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.colorType());
1063f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.alphaType());
1064f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.width());
1065f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.height());
1066f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    p->writeInt32(bitmap.rowBytes());
106732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    p->writeInt32(density);
106832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1069f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bitmap.colorType() == kIndex_8_SkColorType) {
107066ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        // The bitmap needs to be locked to access its color table.
107166ce1c3b1a7b5ed3d4d5a9a05a7c133998c9a73eLeon Scroggins III        SkAutoLockPixels alp(bitmap);
1072f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ctable = bitmap.getColorTable();
107332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ctable != NULL) {
107432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            int count = ctable->count();
107532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(count);
107632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            memcpy(p->writeInplace(count * sizeof(SkPMColor)),
107771487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed                   ctable->readColors(), count * sizeof(SkPMColor));
107832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        } else {
107932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            p->writeInt32(0);   // indicate no ctable
108032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
108132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
108232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1083a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Transfer the underlying ashmem region if we have one and it's immutable.
1084a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::status_t status;
1085c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    int fd = androidBitmap->pixelRef()->getAshmemFd();
1086a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (fd >= 0 && !isMutable && p->allowFds()) {
1087a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1088a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
1089a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                "immutable blob (fds %s)",
1090a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown                p->allowFds() ? "allowed" : "forbidden");
1091a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1092a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1093a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        status = p->writeDupImmutableBlobFileDescriptor(fd);
1094a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        if (status) {
1095a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            doThrowRE(env, "Could not write bitmap blob file descriptor.");
109639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews            return JNI_FALSE;
109739d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews        }
1098a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_TRUE;
1099a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
110032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1101a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    // Copy the bitmap to a new blob.
1102a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bool mutableCopy = isMutable;
1103a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#if DEBUG_PARCEL
1104a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    ALOGD("Bitmap.writeToParcel: copying %s bitmap into new %s blob (fds %s)",
1105a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            isMutable ? "mutable" : "immutable",
1106a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            mutableCopy ? "mutable" : "immutable",
1107a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown            p->allowFds() ? "allowed" : "forbidden");
1108a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown#endif
1109a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1110a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    size_t size = bitmap.getSize();
1111a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    android::Parcel::WritableBlob blob;
1112a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    status = p->writeBlob(size, mutableCopy, &blob);
1113a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (status) {
1114a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        doThrowRE(env, "Could not copy bitmap to parcel blob.");
1115a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        return JNI_FALSE;
111639d7f30ebe490c1d6aee76b0b61e3e67dec13e34Riley Andrews    }
1117a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1118a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.lockPixels();
1119a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    const void* pSrc =  bitmap.getPixels();
1120a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    if (pSrc == NULL) {
1121a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memset(blob.data(), 0, size);
1122a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    } else {
1123a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown        memcpy(blob.data(), pSrc, size);
1124a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    }
1125a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    bitmap.unlockPixels();
1126a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown
1127a316c5dfbc6355f536d765959cacb06bbfed76adJeff Brown    blob.release();
112832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
112932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
113032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
113132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jobject Bitmap_extractAlpha(JNIEnv* env, jobject clazz,
113232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jlong srcHandle, jlong paintHandle,
113332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                   jintArray offsetXY) {
1134f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap src;
1135f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(srcHandle)->getSkBitmap(&src);
11366ba30b85ddfbe37c338ee8dde3dd33322eb38d47Behdad Esfahbod    const android::Paint* paint = reinterpret_cast<android::Paint*>(paintHandle);
113732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkIPoint  offset;
1138f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap dst;
11394508218850faedea95371188da587b6734f5f3dasergeyv    HeapAllocator allocator;
114032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1141f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    src.extractAlpha(&dst, paint, &allocator, &offset);
114232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // If Skia can't allocate pixels for destination bitmap, it resets
114332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // it, that is set its pixels buffer to NULL, and zero width and height.
1144f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (dst.getPixels() == NULL && src.getPixels() != NULL) {
114532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        doThrowOOME(env, "failed to allocate pixels for alpha");
114632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return NULL;
114732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
114832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {
114932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        int* array = env->GetIntArrayElements(offsetXY, NULL);
115032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[0] = offset.fX;
115132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        array[1] = offset.fY;
115232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        env->ReleaseIntArrayElements(offsetXY, array, 0);
115332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
115432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1155c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return createBitmap(env, allocator.getStorageObjAndReset(),
1156f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            getPremulBitmapCreateFlags(true));
115732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
115832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
115932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
116032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
116132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
116257ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y) {
1163f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1164f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
1165f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
116632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1167f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
116832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
116932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
117032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1171f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
117232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
117332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return 0;
117432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
117532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
117632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor dst[1];
1177f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(dst, src, 1, bitmap.getColorTable());
117832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return static_cast<jint>(dst[0]);
117932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
118032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
118132054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
118232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
118357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1184f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1185f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
1186f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
118732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1188f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    ToColorProc proc = ChooseToColorProc(bitmap);
118932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
119032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
119132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
1192f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getAddr(x, y);
119332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == src) {
119432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
119532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
119632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1197f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkColorTable* ctable = bitmap.getColorTable();
119832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    jint* dst = env->GetIntArrayElements(pixelArray, NULL);
119932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor* d = (SkColor*)dst + offset;
120032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    while (--height >= 0) {
120132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        proc(d, src, width, ctable);
120232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        d += stride;
1203f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        src = (void*)((const char*)src + bitmap.rowBytes());
120432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
120532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    env->ReleaseIntArrayElements(pixelArray, dst, 0);
120632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
120732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
120832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
120932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
121032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
121157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint colorHandle) {
1212f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1213f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
121432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    SkColor color = static_cast<SkColor>(colorHandle);
1215f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1216f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bitmap.getPixels()) {
121732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
121832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
121932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1220f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    FromColorProc proc = ChooseFromColorProc(bitmap);
122132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL == proc) {
122232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return;
122332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
122432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1225f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    proc(bitmap.getAddr(x, y), &color, 1, x, y);
1226f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    bitmap.notifyPixelsChanged();
122732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
122832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
122932054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
123032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        jintArray pixelArray, jint offset, jint stride,
123157ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III        jint x, jint y, jint width, jint height) {
1232f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1233f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
123432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
1235f29ed28c7b878ef28058bc730715d0d32445bc57John Reck            x, y, width, height, bitmap);
123632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
123732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
123832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
123932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                      jlong bitmapHandle, jobject jbuffer) {
1240f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1241f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
1242f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1243f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const void* src = bitmap.getPixels();
124432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
124532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != src) {
124632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);
124732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
124832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1249f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(abp.pointer(), src, bitmap.getSize());
125032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
125132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
125232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
125332054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject,
125432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                        jlong bitmapHandle, jobject jbuffer) {
1255f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bitmap;
1256f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bitmapHandle)->getSkBitmap(&bitmap);
1257f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp(bitmap);
1258f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    void* dst = bitmap.getPixels();
125932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
126032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    if (NULL != dst) {
126132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);
126232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        // the java side has already checked that buffer is large enough
1263f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        memcpy(dst, abp.pointer(), bitmap.getSize());
1264f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bitmap.notifyPixelsChanged();
126532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
126632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
126732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
126832054b0b3edb350a5444c47753b2982312dd7ffdChris Craikstatic jboolean Bitmap_sameAs(JNIEnv* env, jobject, jlong bm0Handle,
126932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                              jlong bm1Handle) {
1270f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm0;
1271f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkBitmap bm1;
1272f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bm0Handle)->getSkBitmap(&bm0);
1273f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    reinterpret_cast<Bitmap*>(bm1Handle)->getSkBitmap(&bm1);
1274f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bm0.width() != bm1.width() ||
1275f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bm0.height() != bm1.height() ||
1276f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        bm0.colorType() != bm1.colorType()) {
127732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
127832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
127932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1280f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp0(bm0);
1281f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    SkAutoLockPixels alp1(bm1);
128232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
128332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // if we can't load the pixels, return false
1284f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (NULL == bm0.getPixels() || NULL == bm1.getPixels()) {
128532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        return JNI_FALSE;
128632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
128732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1288f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    if (bm0.colorType() == kIndex_8_SkColorType) {
1289f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct0 = bm0.getColorTable();
1290f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        SkColorTable* ct1 = bm1.getColorTable();
129132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (NULL == ct0 || NULL == ct1) {
129232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
129332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
129432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        if (ct0->count() != ct1->count()) {
129532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
129632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
129732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
129832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        const size_t size = ct0->count() * sizeof(SkPMColor);
129971487eb0ceb2b7dea02649e78d99bb5952f5eaefMike Reed        if (memcmp(ct0->readColors(), ct1->readColors(), size) != 0) {
130032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
130132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
130232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
130332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
130432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // now compare each scanline. We can't do the entire buffer at once,
130532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // since we don't care about the pixel values that might extend beyond
130632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    // the width (since the scanline might be larger than the logical width)
1307f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const int h = bm0.height();
1308f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    const size_t size = bm0.width() * bm0.bytesPerPixel();
130932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    for (int y = 0; y < h; y++) {
131053001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // SkBitmap::getAddr(int, int) may return NULL due to unrecognized config
131153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // (ex: kRLE_Index8_Config). This will cause memcmp method to crash. Since bm0
131253001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // and bm1 both have pixel data() (have passed NULL == getPixels() check),
131353001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // those 2 bitmaps should be valid (only unrecognized), we return JNI_FALSE
131453001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        // to warn user those 2 unrecognized config bitmaps may be different.
1315f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm0Addr = bm0.getAddr(0, y);
1316f29ed28c7b878ef28058bc730715d0d32445bc57John Reck        void *bm1Addr = bm1.getAddr(0, y);
131753001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
131853001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if(bm0Addr == NULL || bm1Addr == NULL) {
131953001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen            return JNI_FALSE;
132053001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        }
132153001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen
132253001ca3a629c0069f4fdac44f7711ad4a0c395ahenry.uh_chen        if (memcmp(bm0Addr, bm1Addr, size) != 0) {
132332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik            return JNI_FALSE;
132432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        }
132532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    }
132632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    return JNI_TRUE;
132732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik}
132832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
1329c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reckstatic jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
1330f29ed28c7b878ef28058bc730715d0d32445bc57John Reck    LocalScopedBitmap bitmap(bitmapHandle);
1331c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkPixelRef* pixelRef = bitmap->pixelRef();
1332c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck    SkSafeRef(pixelRef);
1333c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck    return reinterpret_cast<jlong>(pixelRef);
1334c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck}
1335c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck
13364387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reckstatic void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
13374387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    LocalScopedBitmap bitmapHandle(bitmapPtr);
13384387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    if (!bitmapHandle.valid()) return;
13394387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    SkBitmap bitmap;
13404387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    bitmapHandle->getSkBitmap(&bitmap);
13414387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    android::uirenderer::renderthread::RenderProxy::prepareToDraw(bitmap);
13424387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck}
13434387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck
13444508218850faedea95371188da587b6734f5f3dasergeyvstatic jint Bitmap_getAllocationByteCount(JNIEnv* env, jobject, jlong bitmapPtr) {
13454508218850faedea95371188da587b6734f5f3dasergeyv    LocalScopedBitmap bitmapHandle(bitmapPtr);
13464508218850faedea95371188da587b6734f5f3dasergeyv    return static_cast<jint>(bitmapHandle->getAllocationByteCount());
13474508218850faedea95371188da587b6734f5f3dasergeyv}
13484508218850faedea95371188da587b6734f5f3dasergeyv
134932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik///////////////////////////////////////////////////////////////////////////////
1350c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jclass make_globalref(JNIEnv* env, const char classname[])
1351c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1352c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jclass c = env->FindClass(classname);
1353c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(c);
1354c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return (jclass) env->NewGlobalRef(c);
1355c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
1356c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv
1357c69853c8b72540e5031d28e03cbce5a390c6959fsergeyvstatic jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
1358c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv                                const char fieldname[], const char type[])
1359c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv{
1360c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    jfieldID id = env->GetFieldID(clazz, fieldname, type);
1361c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    SkASSERT(id);
1362c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    return id;
1363c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}
136432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
136576f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gBitmapMethods[] = {
136632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreate",             "([IIIIIIZ)Landroid/graphics/Bitmap;",
136732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_creator },
136832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
136932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_copy },
1370721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews    {   "nativeCopyAshmem",         "(J)Landroid/graphics/Bitmap;",
1371721ae5fec5f1fd4f93aa2a361a0ac298e15ce353Riley Andrews        (void*)Bitmap_copyAshmem },
1372a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson    {   "nativeCopyAshmemConfig",   "(JI)Landroid/graphics/Bitmap;",
1373a5fdde9d15fbdf1aaeb61e1cf0c128af3aeb7b67Winson        (void*)Bitmap_copyAshmemConfig },
1374775873a66a946fae2b0535abb51df9817bd1b20cRichard Uhler    {   "nativeGetNativeFinalizer", "()J", (void*)Bitmap_getNativeFinalizer },
137532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRecycle",            "(J)Z", (void*)Bitmap_recycle },
13764508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeReconfigure",        "(JIIIZ)V", (void*)Bitmap_reconfigure },
137732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
137832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_compress },
137932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
138032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
138132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
138232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
138357ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeIsPremultiplied",    "(J)Z", (void*)Bitmap_isPremultiplied},
138457ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetHasAlpha",        "(JZZ)V", (void*)Bitmap_setHasAlpha},
138557ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPremultiplied",   "(JZ)V", (void*)Bitmap_setPremultiplied},
138632054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeHasMipMap",          "(J)Z", (void*)Bitmap_hasMipMap },
138732054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSetHasMipMap",       "(JZ)V", (void*)Bitmap_setHasMipMap },
138832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCreateFromParcel",
138932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        "(Landroid/os/Parcel;)Landroid/graphics/Bitmap;",
139032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_createFromParcel },
139132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeWriteToParcel",      "(JZILandroid/os/Parcel;)Z",
139232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_writeToParcel },
139332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeExtractAlpha",       "(JJ[I)Landroid/graphics/Bitmap;",
139432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik        (void*)Bitmap_extractAlpha },
139532054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeGenerationId",       "(J)I", (void*)Bitmap_getGenerationId },
139657ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixel",           "(JII)I", (void*)Bitmap_getPixel },
139757ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeGetPixels",          "(J[IIIIIII)V", (void*)Bitmap_getPixels },
139857ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixel",           "(JIII)V", (void*)Bitmap_setPixel },
139957ee620ced8caed1eb8651717f6a6d2d5f1f9a5bLeon Scroggins III    {   "nativeSetPixels",          "(J[IIIIIII)V", (void*)Bitmap_setPixels },
140032054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsToBuffer", "(JLjava/nio/Buffer;)V",
140132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsToBuffer },
140232054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
140332054b0b3edb350a5444c47753b2982312dd7ffdChris Craik                                            (void*)Bitmap_copyPixelsFromBuffer },
140432054b0b3edb350a5444c47753b2982312dd7ffdChris Craik    {   "nativeSameAs",             "(JJ)Z", (void*)Bitmap_sameAs },
1405c6e2e8ff474ae44bab5b9eb665851118abd27b68John Reck    {   "nativeRefPixelRef",        "(J)J", (void*)Bitmap_refPixelRef },
14064387190d8ec9fe4e953fcfeb093a644b82cf85edJohn Reck    {   "nativePrepareToDraw",      "(J)V", (void*)Bitmap_prepareToDraw },
14074508218850faedea95371188da587b6734f5f3dasergeyv    {   "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
140832054b0b3edb350a5444c47753b2982312dd7ffdChris Craik};
140932054b0b3edb350a5444c47753b2982312dd7ffdChris Craik
141032054b0b3edb350a5444c47753b2982312dd7ffdChris Craikint register_android_graphics_Bitmap(JNIEnv* env)
141132054b0b3edb350a5444c47753b2982312dd7ffdChris Craik{
1412c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
1413c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
1414c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
1415c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
1416c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv    gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
1417ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe    return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
1418ed6b9dff563c5e22f040ff37e12c0d771e0478aeAndreas Gampe                                         NELEM(gBitmapMethods));
1419c69853c8b72540e5031d28e03cbce5a390c6959fsergeyv}