• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkRegion.h"
2 #include "SkPath.h"
3 #include "GraphicsJNI.h"
4 
5 #include <jni.h>
6 
7 static jfieldID gRegion_nativeInstanceFieldID;
8 
GetSkRegion(JNIEnv * env,jobject regionObject)9 static inline SkRegion* GetSkRegion(JNIEnv* env, jobject regionObject) {
10     SkRegion* rgn = (SkRegion*)env->GetIntField(regionObject, gRegion_nativeInstanceFieldID);
11     SkASSERT(rgn != NULL);
12     return rgn;
13 }
14 
Region_constructor(JNIEnv * env,jobject)15 static SkRegion* Region_constructor(JNIEnv* env, jobject) {
16     return new SkRegion;
17 }
18 
Region_destructor(JNIEnv * env,jobject,SkRegion * region)19 static void Region_destructor(JNIEnv* env, jobject, SkRegion* region) {
20     SkASSERT(region);
21     delete region;
22 }
23 
Region_setRegion(JNIEnv * env,jobject,SkRegion * dst,const SkRegion * src)24 static void Region_setRegion(JNIEnv* env, jobject, SkRegion* dst, const SkRegion* src) {
25     SkASSERT(dst && src);
26     *dst = *src;
27 }
28 
Region_setRect(JNIEnv * env,jobject,SkRegion * dst,int left,int top,int right,int bottom)29 static jboolean Region_setRect(JNIEnv* env, jobject, SkRegion* dst, int left, int top, int right, int bottom) {
30     return dst->setRect(left, top, right, bottom);
31 }
32 
Region_setPath(JNIEnv * env,jobject,SkRegion * dst,const SkPath * path,const SkRegion * clip)33 static jboolean Region_setPath(JNIEnv* env, jobject, SkRegion* dst,
34                                const SkPath* path, const SkRegion* clip) {
35     SkASSERT(dst && path && clip);
36     return dst->setPath(*path, *clip);
37 }
38 
Region_getBounds(JNIEnv * env,jobject,SkRegion * region,jobject rectBounds)39 static jboolean Region_getBounds(JNIEnv* env, jobject, SkRegion* region, jobject rectBounds) {
40     GraphicsJNI::irect_to_jrect(region->getBounds(), env, rectBounds);
41     return !region->isEmpty();
42 }
43 
Region_getBoundaryPath(JNIEnv * env,jobject,const SkRegion * region,SkPath * path)44 static jboolean Region_getBoundaryPath(JNIEnv* env, jobject, const SkRegion* region, SkPath* path) {
45     return region->getBoundaryPath(path);
46 }
47 
Region_op0(JNIEnv * env,jobject,SkRegion * dst,int left,int top,int right,int bottom,int op)48 static jboolean Region_op0(JNIEnv* env, jobject, SkRegion* dst, int left, int top, int right, int bottom, int op) {
49     SkIRect ir;
50 
51     ir.set(left, top, right, bottom);
52     return dst->op(ir, (SkRegion::Op)op);
53 }
54 
Region_op1(JNIEnv * env,jobject,SkRegion * dst,jobject rectObject,const SkRegion * region,int op)55 static jboolean Region_op1(JNIEnv* env, jobject, SkRegion* dst, jobject rectObject, const SkRegion* region, int op) {
56     SkIRect    ir;
57     GraphicsJNI::jrect_to_irect(env, rectObject, &ir);
58     return dst->op(ir, *region, (SkRegion::Op)op);
59 }
60 
Region_op2(JNIEnv * env,jobject,SkRegion * dst,const SkRegion * region1,const SkRegion * region2,int op)61 static jboolean Region_op2(JNIEnv* env, jobject, SkRegion* dst, const SkRegion* region1, const SkRegion* region2, int op) {
62     return dst->op(*region1, *region2, (SkRegion::Op)op);
63 }
64 
65 ////////////////////////////////////  These are methods, not static
66 
Region_isEmpty(JNIEnv * env,jobject region)67 static jboolean Region_isEmpty(JNIEnv* env, jobject region) {
68     return GetSkRegion(env, region)->isEmpty();
69 }
70 
Region_isRect(JNIEnv * env,jobject region)71 static jboolean Region_isRect(JNIEnv* env, jobject region) {
72     return GetSkRegion(env, region)->isRect();
73 }
74 
Region_isComplex(JNIEnv * env,jobject region)75 static jboolean Region_isComplex(JNIEnv* env, jobject region) {
76     return GetSkRegion(env, region)->isComplex();
77 }
78 
Region_contains(JNIEnv * env,jobject region,int x,int y)79 static jboolean Region_contains(JNIEnv* env, jobject region, int x, int y) {
80     return GetSkRegion(env, region)->contains(x, y);
81 }
82 
Region_quickContains(JNIEnv * env,jobject region,int left,int top,int right,int bottom)83 static jboolean Region_quickContains(JNIEnv* env, jobject region, int left, int top, int right, int bottom) {
84     return GetSkRegion(env, region)->quickContains(left, top, right, bottom);
85 }
86 
Region_quickRejectIIII(JNIEnv * env,jobject region,int left,int top,int right,int bottom)87 static jboolean Region_quickRejectIIII(JNIEnv* env, jobject region, int left, int top, int right, int bottom) {
88     SkIRect ir;
89     ir.set(left, top, right, bottom);
90     return GetSkRegion(env, region)->quickReject(ir);
91 }
92 
Region_quickRejectRgn(JNIEnv * env,jobject region,jobject other)93 static jboolean Region_quickRejectRgn(JNIEnv* env, jobject region, jobject other) {
94     return GetSkRegion(env, region)->quickReject(*GetSkRegion(env, other));
95 }
96 
Region_translate(JNIEnv * env,jobject region,int x,int y,jobject dst)97 static void Region_translate(JNIEnv* env, jobject region, int x, int y, jobject dst) {
98     SkRegion* rgn = GetSkRegion(env, region);
99     if (dst)
100         rgn->translate(x, y, GetSkRegion(env, dst));
101     else
102         rgn->translate(x, y);
103 }
104 
105 // Scale the rectangle by given scale and set the reuslt to the dst.
scale_rect(SkIRect * dst,const SkIRect & src,float scale)106 static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
107    dst->fLeft = (int)::roundf(src.fLeft * scale);
108    dst->fTop = (int)::roundf(src.fTop * scale);
109    dst->fRight = (int)::roundf(src.fRight * scale);
110    dst->fBottom = (int)::roundf(src.fBottom * scale);
111 }
112 
113 // Scale the region by given scale and set the reuslt to the dst.
114 // dest and src can be the same region instance.
scale_rgn(SkRegion * dst,const SkRegion & src,float scale)115 static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
116    SkRegion tmp;
117    SkRegion::Iterator iter(src);
118 
119    for (; !iter.done(); iter.next()) {
120        SkIRect r;
121        scale_rect(&r, iter.rect(), scale);
122        tmp.op(r, SkRegion::kUnion_Op);
123    }
124    dst->swap(tmp);
125 }
126 
Region_scale(JNIEnv * env,jobject region,jfloat scale,jobject dst)127 static void Region_scale(JNIEnv* env, jobject region, jfloat scale, jobject dst) {
128     SkRegion* rgn = GetSkRegion(env, region);
129     if (dst)
130         scale_rgn(GetSkRegion(env, dst), *rgn, scale);
131     else
132         scale_rgn(rgn, *rgn, scale);
133 }
134 
135 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
136 
137 #include <binder/Parcel.h>
138 #include "android_util_Binder.h"
139 
Region_createFromParcel(JNIEnv * env,jobject clazz,jobject parcel)140 static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel)
141 {
142     if (parcel == NULL) {
143         return NULL;
144     }
145 
146     android::Parcel* p = android::parcelForJavaObject(env, parcel);
147 
148     SkRegion* region = new SkRegion;
149     size_t size = p->readInt32();
150     region->unflatten(p->readInplace(size));
151 
152     return region;
153 }
154 
Region_writeToParcel(JNIEnv * env,jobject clazz,const SkRegion * region,jobject parcel)155 static jboolean Region_writeToParcel(JNIEnv* env, jobject clazz, const SkRegion* region, jobject parcel)
156 {
157     if (parcel == NULL) {
158         return false;
159     }
160 
161     android::Parcel* p = android::parcelForJavaObject(env, parcel);
162 
163     size_t size = region->flatten(NULL);
164     p->writeInt32(size);
165     region->flatten(p->writeInplace(size));
166 
167     return true;
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
171 
Region_equals(JNIEnv * env,jobject clazz,const SkRegion * r1,const SkRegion * r2)172 static jboolean Region_equals(JNIEnv* env, jobject clazz, const SkRegion *r1, const SkRegion* r2)
173 {
174   return (jboolean) (*r1 == *r2);
175 }
176 
177 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
178 
179 struct RgnIterPair {
180     SkRegion            fRgn;   // a copy of the caller's region
181     SkRegion::Iterator  fIter;  // an iterator acting upon the copy (fRgn)
182 
RgnIterPairRgnIterPair183     RgnIterPair(const SkRegion& rgn) : fRgn(rgn) {
184         // have our iterator reference our copy (fRgn), so we know it will be
185         // unchanged for the lifetime of the iterator
186         fIter.reset(fRgn);
187     }
188 };
189 
RegionIter_constructor(JNIEnv * env,jobject,const SkRegion * region)190 static RgnIterPair* RegionIter_constructor(JNIEnv* env, jobject, const SkRegion* region)
191 {
192     SkASSERT(region);
193     return new RgnIterPair(*region);
194 }
195 
RegionIter_destructor(JNIEnv * env,jobject,RgnIterPair * pair)196 static void RegionIter_destructor(JNIEnv* env, jobject, RgnIterPair* pair)
197 {
198     SkASSERT(pair);
199     delete pair;
200 }
201 
RegionIter_next(JNIEnv * env,jobject,RgnIterPair * pair,jobject rectObject)202 static jboolean RegionIter_next(JNIEnv* env, jobject, RgnIterPair* pair, jobject rectObject)
203 {
204     // the caller has checked that rectObject is not nul
205     SkASSERT(pair);
206     SkASSERT(rectObject);
207 
208     if (!pair->fIter.done()) {
209         GraphicsJNI::irect_to_jrect(pair->fIter.rect(), env, rectObject);
210         pair->fIter.next();
211         return true;
212     }
213     return false;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
217 
218 #include <android_runtime/AndroidRuntime.h>
219 
220 static JNINativeMethod gRegionIterMethods[] = {
221     { "nativeConstructor",  "(I)I",                         (void*)RegionIter_constructor   },
222     { "nativeDestructor",   "(I)V",                         (void*)RegionIter_destructor    },
223     { "nativeNext",         "(ILandroid/graphics/Rect;)Z",  (void*)RegionIter_next          }
224 };
225 
226 static JNINativeMethod gRegionMethods[] = {
227     // these are static methods
228     { "nativeConstructor",      "()I",                              (void*)Region_constructor       },
229     { "nativeDestructor",       "(I)V",                             (void*)Region_destructor        },
230     { "nativeSetRegion",        "(II)Z",                            (void*)Region_setRegion         },
231     { "nativeSetRect",          "(IIIII)Z",                         (void*)Region_setRect           },
232     { "nativeSetPath",          "(III)Z",                           (void*)Region_setPath           },
233     { "nativeGetBounds",        "(ILandroid/graphics/Rect;)Z",      (void*)Region_getBounds         },
234     { "nativeGetBoundaryPath",  "(II)Z",                            (void*)Region_getBoundaryPath   },
235     { "nativeOp",               "(IIIIII)Z",                        (void*)Region_op0               },
236     { "nativeOp",               "(ILandroid/graphics/Rect;II)Z",    (void*)Region_op1               },
237     { "nativeOp",               "(IIII)Z",                          (void*)Region_op2               },
238     // these are methods that take the java region object
239     { "isEmpty",                "()Z",                              (void*)Region_isEmpty           },
240     { "isRect",                 "()Z",                              (void*)Region_isRect            },
241     { "isComplex",              "()Z",                              (void*)Region_isComplex         },
242     { "contains",               "(II)Z",                            (void*)Region_contains          },
243     { "quickContains",          "(IIII)Z",                          (void*)Region_quickContains     },
244     { "quickReject",            "(IIII)Z",                          (void*)Region_quickRejectIIII   },
245     { "quickReject",            "(Landroid/graphics/Region;)Z",     (void*)Region_quickRejectRgn    },
246     { "scale",                  "(FLandroid/graphics/Region;)V",    (void*)Region_scale             },
247     { "translate",              "(IILandroid/graphics/Region;)V",   (void*)Region_translate         },
248     // parceling methods
249     { "nativeCreateFromParcel", "(Landroid/os/Parcel;)I",           (void*)Region_createFromParcel  },
250     { "nativeWriteToParcel",    "(ILandroid/os/Parcel;)Z",          (void*)Region_writeToParcel     },
251     { "nativeEquals",           "(II)Z",                            (void*)Region_equals            },
252 };
253 
254 int register_android_graphics_Region(JNIEnv* env);
register_android_graphics_Region(JNIEnv * env)255 int register_android_graphics_Region(JNIEnv* env)
256 {
257     jclass clazz = env->FindClass("android/graphics/Region");
258     SkASSERT(clazz);
259 
260     gRegion_nativeInstanceFieldID = env->GetFieldID(clazz, "mNativeRegion", "I");
261     SkASSERT(gRegion_nativeInstanceFieldID);
262 
263     int result = android::AndroidRuntime::registerNativeMethods(env, "android/graphics/Region",
264                                                              gRegionMethods, SK_ARRAY_COUNT(gRegionMethods));
265     if (result < 0)
266         return result;
267 
268     return android::AndroidRuntime::registerNativeMethods(env, "android/graphics/RegionIterator",
269                                                        gRegionIterMethods, SK_ARRAY_COUNT(gRegionIterMethods));
270 }
271