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