GraphicsJNI.h revision a2f0e2d6b7f9dff3a52dd78d6db307070a71e9b2
1#ifndef GraphicsJNI_DEFINED
2#define GraphicsJNI_DEFINED
3
4#include "SkBitmap.h"
5#include "SkDevice.h"
6#include "SkPixelRef.h"
7#include "SkMallocPixelRef.h"
8#include "SkPoint.h"
9#include "SkRect.h"
10#include "../images/SkBitmapRegionDecoder.h"
11#include "../images/SkImageDecoder.h"
12#include <jni.h>
13
14class SkCanvas;
15class SkPaint;
16class SkPicture;
17
18class GraphicsJNI {
19public:
20    // returns true if an exception is set (and dumps it out to the Log)
21    static bool hasException(JNIEnv*);
22
23    static void get_jrect(JNIEnv*, jobject jrect, int* L, int* T, int* R, int* B);
24    static void set_jrect(JNIEnv*, jobject jrect, int L, int T, int R, int B);
25
26    static SkIRect* jrect_to_irect(JNIEnv*, jobject jrect, SkIRect*);
27    static void irect_to_jrect(const SkIRect&, JNIEnv*, jobject jrect);
28
29    static SkRect* jrectf_to_rect(JNIEnv*, jobject jrectf, SkRect*);
30    static SkRect* jrect_to_rect(JNIEnv*, jobject jrect, SkRect*);
31    static void rect_to_jrectf(const SkRect&, JNIEnv*, jobject jrectf);
32
33    static void set_jpoint(JNIEnv*, jobject jrect, int x, int y);
34
35    static SkIPoint* jpoint_to_ipoint(JNIEnv*, jobject jpoint, SkIPoint* point);
36    static void ipoint_to_jpoint(const SkIPoint& point, JNIEnv*, jobject jpoint);
37
38    static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
39    static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
40
41    static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
42    static SkPaint*  getNativePaint(JNIEnv*, jobject paint);
43    static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
44    static SkPicture* getNativePicture(JNIEnv*, jobject picture);
45    static SkRegion* getNativeRegion(JNIEnv*, jobject region);
46
47    /** Return the corresponding native config from the java Config enum,
48        or kNo_Config if the java object is null.
49    */
50    static SkBitmap::Config getNativeBitmapConfig(JNIEnv*, jobject jconfig);
51
52    /** Create a java Bitmap object given the native bitmap (required) and optional
53        storage array (may be null).
54    */
55    static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
56                                bool isMutable, jbyteArray ninepatch, int density = -1);
57
58    static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
59                                jbyteArray ninepatch, int density = -1);
60
61    static jobject createRegion(JNIEnv* env, SkRegion* region);
62
63    static jobject createBitmapRegionDecoder(JNIEnv* env, SkBitmapRegionDecoder* bitmap);
64
65    static jbyteArray allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
66                                     SkColorTable* ctable);
67
68    /** Set a pixelref for the bitmap (needs setConfig to already be called)
69        Returns true on success. If it returns false, then it failed, and the
70        appropriate exception will have been raised.
71    */
72    static bool mallocPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable);
73
74    /** Copy the colors in colors[] to the bitmap, convert to the correct
75        format along the way.
76    */
77    static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
78                          int srcStride, int x, int y, int width, int height,
79                          const SkBitmap& dstBitmap);
80
81    static jbyteArray getBitmapStorageObj(SkPixelRef *pixref);
82};
83
84class AndroidPixelRef : public SkMallocPixelRef {
85public:
86    AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
87                    SkColorTable* ctable);
88
89    virtual ~AndroidPixelRef();
90
91    jbyteArray getStorageObj() { return fStorageObj; }
92
93    void setLocalJNIRef(jbyteArray arr);
94
95    /** Used to hold a ref to the pixels when the Java bitmap may be collected.
96     *  If specified, 'localref' is a valid JNI local reference to the byte array
97     *  containing the pixel data.
98     *
99     *  'localref' may only be NULL if setLocalJNIRef() was already called with
100     *  a JNI local ref that is still valid.
101     */
102    virtual void globalRef(void* localref=NULL);
103
104    /** Release a ref that was acquired using globalRef(). */
105    virtual void globalUnref();
106
107private:
108    JavaVM* fVM;
109    bool fOnJavaHeap; // If true, the memory was allocated on the Java heap
110
111    jbyteArray fStorageObj; // The Java byte[] object used as the bitmap backing store
112    bool fHasGlobalRef; // If true, fStorageObj holds a JNI global ref
113
114    mutable int32_t fGlobalRefCnt;
115};
116
117/** A helper class for accessing Java-heap-allocated bitmaps.
118 *  This should be used when calling into a JNI method that retains a
119 *  reference to the bitmap longer than the lifetime of the Java Bitmap.
120 *
121 *  After creating an instance of this class, a call to
122 *  AndroidPixelRef::globalRef() will allocate a JNI global reference
123 *  to the backing buffer object.
124 */
125class JavaHeapBitmapRef {
126public:
127
128    JavaHeapBitmapRef(JNIEnv *env, SkBitmap* nativeBitmap, jbyteArray buffer);
129    ~JavaHeapBitmapRef();
130
131private:
132    JNIEnv* fEnv;
133    SkBitmap* fNativeBitmap;
134    jbyteArray fBuffer;
135};
136
137/** Allocator which allocates the backing buffer in the Java heap.
138 *  Instances can only be used to perform a single allocation, which helps
139 *  ensure that the allocated buffer is properly accounted for with a
140 *  reference in the heap (or a JNI global reference).
141 */
142class JavaPixelAllocator : public SkBitmap::Allocator {
143public:
144    JavaPixelAllocator(JNIEnv* env, bool allocateInJavaHeap=true);
145    // overrides
146    virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable);
147
148    /** Return the Java array object created for the last allocation.
149     *  This returns a local JNI reference which the caller is responsible
150     *  for storing appropriately (usually by passing it to the Bitmap
151     *  constructor).
152     */
153    jbyteArray getStorageObj() { return fStorageObj; }
154
155    /** Same as getStorageObj(), but also resets the allocator so that it
156     *  can allocate again.
157     */
158    jbyteArray getStorageObjAndReset() {
159        jbyteArray result = fStorageObj;
160        fStorageObj = NULL;
161        fAllocCount = 0;
162        return result;
163    };
164
165private:
166    JavaVM* fVM;
167    bool fAllocateInJavaHeap;
168    jbyteArray fStorageObj;
169    int fAllocCount;
170};
171
172class JavaMemoryUsageReporter : public SkVMMemoryReporter {
173public:
174    JavaMemoryUsageReporter(JNIEnv* env);
175    virtual ~JavaMemoryUsageReporter();
176    // overrides
177    virtual bool reportMemory(size_t memorySize);
178
179private:
180    JavaVM* fVM;
181    size_t fTotalSize;
182};
183
184enum JNIAccess {
185    kRO_JNIAccess,
186    kRW_JNIAccess
187};
188
189class AutoJavaFloatArray {
190public:
191    AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
192                       int minLength = 0, JNIAccess = kRW_JNIAccess);
193    ~AutoJavaFloatArray();
194
195    float* ptr() const { return fPtr; }
196    int    length() const { return fLen; }
197
198private:
199    JNIEnv*     fEnv;
200    jfloatArray fArray;
201    float*      fPtr;
202    int         fLen;
203    int         fReleaseMode;
204};
205
206class AutoJavaIntArray {
207public:
208    AutoJavaIntArray(JNIEnv* env, jintArray array, int minLength = 0);
209    ~AutoJavaIntArray();
210
211    jint* ptr() const { return fPtr; }
212    int    length() const { return fLen; }
213
214private:
215    JNIEnv*     fEnv;
216    jintArray fArray;
217    jint*      fPtr;
218    int         fLen;
219};
220
221class AutoJavaShortArray {
222public:
223    AutoJavaShortArray(JNIEnv* env, jshortArray array,
224                       int minLength = 0, JNIAccess = kRW_JNIAccess);
225    ~AutoJavaShortArray();
226
227    jshort* ptr() const { return fPtr; }
228    int    length() const { return fLen; }
229
230private:
231    JNIEnv*     fEnv;
232    jshortArray fArray;
233    jshort*      fPtr;
234    int         fLen;
235    int         fReleaseMode;
236};
237
238class AutoJavaByteArray {
239public:
240    AutoJavaByteArray(JNIEnv* env, jbyteArray array, int minLength = 0);
241    ~AutoJavaByteArray();
242
243    jbyte* ptr() const { return fPtr; }
244    int    length() const { return fLen; }
245
246private:
247    JNIEnv*     fEnv;
248    jbyteArray fArray;
249    jbyte*      fPtr;
250    int         fLen;
251};
252
253void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL);
254void doThrowNPE(JNIEnv* env);
255void doThrowAIOOBE(JNIEnv* env); // Array Index Out Of Bounds Exception
256void doThrowIAE(JNIEnv* env, const char* msg = NULL);   // Illegal Argument
257void doThrowRE(JNIEnv* env, const char* msg = NULL);   // Runtime
258void doThrowISE(JNIEnv* env, const char* msg = NULL);   // Illegal State
259void doThrowOOME(JNIEnv* env, const char* msg = NULL);   // Out of memory
260void doThrowIOE(JNIEnv* env, const char* msg = NULL);   // IO Exception
261
262#define NPE_CHECK_RETURN_ZERO(env, object)    \
263    do { if (NULL == (object)) { doThrowNPE(env); return 0; } } while (0)
264
265#define NPE_CHECK_RETURN_VOID(env, object)    \
266    do { if (NULL == (object)) { doThrowNPE(env); return; } } while (0)
267
268#endif
269