Region.cpp revision 54b6cfa9a9e5b861a9930af873580d6dc20f773c
1#include "SkRegion.h"
2#include "SkPath.h"
3#include "GraphicsJNI.h"
4
5#include <jni.h>
6
7static jfieldID gRegion_nativeInstanceFieldID;
8
9static 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
15static SkRegion* Region_constructor(JNIEnv* env, jobject) {
16    return new SkRegion;
17}
18
19static void Region_destructor(JNIEnv* env, jobject, SkRegion* region) {
20    SkASSERT(region);
21    delete region;
22}
23
24static void Region_setRegion(JNIEnv* env, jobject, SkRegion* dst, const SkRegion* src) {
25    SkASSERT(dst && src);
26    *dst = *src;
27}
28
29static 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
33static 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
39static 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
44static jboolean Region_getBoundaryPath(JNIEnv* env, jobject, const SkRegion* region, SkPath* path) {
45    return region->getBoundaryPath(path);
46}
47
48static 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
55static 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
61static 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
67static jboolean Region_isEmpty(JNIEnv* env, jobject region) {
68    return GetSkRegion(env, region)->isEmpty();
69}
70
71static jboolean Region_isRect(JNIEnv* env, jobject region) {
72    return GetSkRegion(env, region)->isRect();
73}
74
75static jboolean Region_isComplex(JNIEnv* env, jobject region) {
76    return GetSkRegion(env, region)->isComplex();
77}
78
79static jboolean Region_contains(JNIEnv* env, jobject region, int x, int y) {
80    return GetSkRegion(env, region)->contains(x, y);
81}
82
83static 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
87static 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
93static jboolean Region_quickRejectRgn(JNIEnv* env, jobject region, jobject other) {
94    return GetSkRegion(env, region)->quickReject(*GetSkRegion(env, other));
95}
96
97static 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////////////////////////////////////////////////////////////////////////////////////////////////////////////
106
107#include "Parcel.h"
108#include "android_util_Binder.h"
109
110static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel)
111{
112    if (parcel == NULL) {
113        return NULL;
114    }
115
116    android::Parcel* p = android::parcelForJavaObject(env, parcel);
117
118    SkRegion* region = new SkRegion;
119    size_t size = p->readInt32();
120    region->unflatten(p->readInplace(size));
121
122    return region;
123}
124
125static jboolean Region_writeToParcel(JNIEnv* env, jobject clazz, const SkRegion* region, jobject parcel)
126{
127    if (parcel == NULL) {
128        return false;
129    }
130
131    android::Parcel* p = android::parcelForJavaObject(env, parcel);
132
133    size_t size = region->flatten(NULL);
134    p->writeInt32(size);
135    region->flatten(p->writeInplace(size));
136
137    return true;
138}
139
140////////////////////////////////////////////////////////////////////////////////////////////////////////////
141
142struct RgnIterPair {
143    SkRegion            fRgn;   // a copy of the caller's region
144    SkRegion::Iterator  fIter;  // an iterator acting upon the copy (fRgn)
145
146    RgnIterPair(const SkRegion& rgn) : fRgn(rgn) {
147        // have our iterator reference our copy (fRgn), so we know it will be
148        // unchanged for the lifetime of the iterator
149        fIter.reset(fRgn);
150    }
151};
152
153static RgnIterPair* RegionIter_constructor(JNIEnv* env, jobject, const SkRegion* region)
154{
155    SkASSERT(region);
156    return new RgnIterPair(*region);
157}
158
159static void RegionIter_destructor(JNIEnv* env, jobject, RgnIterPair* pair)
160{
161    SkASSERT(pair);
162    delete pair;
163}
164
165static jboolean RegionIter_next(JNIEnv* env, jobject, RgnIterPair* pair, jobject rectObject)
166{
167    // the caller has checked that rectObject is not nul
168    SkASSERT(pair);
169    SkASSERT(rectObject);
170
171    if (!pair->fIter.done()) {
172        GraphicsJNI::irect_to_jrect(pair->fIter.rect(), env, rectObject);
173        pair->fIter.next();
174        return true;
175    }
176    return false;
177}
178
179////////////////////////////////////////////////////////////////////////////////////////////////////////////
180
181#include <android_runtime/AndroidRuntime.h>
182
183static JNINativeMethod gRegionIterMethods[] = {
184    { "nativeConstructor",  "(I)I",                         (void*)RegionIter_constructor   },
185    { "nativeDestructor",   "(I)V",                         (void*)RegionIter_destructor    },
186    { "nativeNext",         "(ILandroid/graphics/Rect;)Z",  (void*)RegionIter_next          }
187};
188
189static JNINativeMethod gRegionMethods[] = {
190    // these are static methods
191    { "nativeConstructor",      "()I",                              (void*)Region_constructor       },
192    { "nativeDestructor",       "(I)V",                             (void*)Region_destructor        },
193    { "nativeSetRegion",        "(II)Z",                            (void*)Region_setRegion         },
194    { "nativeSetRect",          "(IIIII)Z",                         (void*)Region_setRect           },
195    { "nativeSetPath",          "(III)Z",                           (void*)Region_setPath           },
196    { "nativeGetBounds",        "(ILandroid/graphics/Rect;)Z",      (void*)Region_getBounds         },
197    { "nativeGetBoundaryPath",  "(II)Z",                            (void*)Region_getBoundaryPath   },
198    { "nativeOp",               "(IIIIII)Z",                        (void*)Region_op0               },
199    { "nativeOp",               "(ILandroid/graphics/Rect;II)Z",    (void*)Region_op1               },
200    { "nativeOp",               "(IIII)Z",                          (void*)Region_op2               },
201    // these are methods that take the java region object
202    { "isEmpty",                "()Z",                              (void*)Region_isEmpty           },
203    { "isRect",                 "()Z",                              (void*)Region_isRect            },
204    { "isComplex",              "()Z",                              (void*)Region_isComplex         },
205    { "contains",               "(II)Z",                            (void*)Region_contains          },
206    { "quickContains",          "(IIII)Z",                          (void*)Region_quickContains     },
207    { "quickReject",            "(IIII)Z",                          (void*)Region_quickRejectIIII   },
208    { "quickReject",            "(Landroid/graphics/Region;)Z",     (void*)Region_quickRejectRgn    },
209    { "translate",              "(IILandroid/graphics/Region;)V",   (void*)Region_translate         },
210    // parceling methods
211    { "nativeCreateFromParcel", "(Landroid/os/Parcel;)I",           (void*)Region_createFromParcel  },
212    { "nativeWriteToParcel",    "(ILandroid/os/Parcel;)Z",          (void*)Region_writeToParcel     }
213};
214
215int register_android_graphics_Region(JNIEnv* env);
216int register_android_graphics_Region(JNIEnv* env)
217{
218    jclass clazz = env->FindClass("android/graphics/Region");
219    SkASSERT(clazz);
220
221    gRegion_nativeInstanceFieldID = env->GetFieldID(clazz, "mNativeRegion", "I");
222    SkASSERT(gRegion_nativeInstanceFieldID);
223
224    int result = android::AndroidRuntime::registerNativeMethods(env, "android/graphics/Region",
225                                                             gRegionMethods, SK_ARRAY_COUNT(gRegionMethods));
226    if (result < 0)
227        return result;
228
229    return android::AndroidRuntime::registerNativeMethods(env, "android/graphics/RegionIterator",
230                                                       gRegionIterMethods, SK_ARRAY_COUNT(gRegionIterMethods));
231}
232