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