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