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