xref: /aosp_15_r20/frameworks/base/libs/hwui/jni/Region.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #include "SkRegion.h"
18*d57664e9SAndroid Build Coastguard Worker #include "SkPath.h"
19*d57664e9SAndroid Build Coastguard Worker #include "GraphicsJNI.h"
20*d57664e9SAndroid Build Coastguard Worker 
21*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__ // Layoutlib does not support parcel
22*d57664e9SAndroid Build Coastguard Worker #include <android/binder_parcel.h>
23*d57664e9SAndroid Build Coastguard Worker #include <android/binder_parcel_jni.h>
24*d57664e9SAndroid Build Coastguard Worker #include <android/binder_parcel_utils.h>
25*d57664e9SAndroid Build Coastguard Worker #endif
26*d57664e9SAndroid Build Coastguard Worker 
27*d57664e9SAndroid Build Coastguard Worker namespace android {
28*d57664e9SAndroid Build Coastguard Worker 
29*d57664e9SAndroid Build Coastguard Worker static jfieldID gRegion_nativeInstanceFieldID;
30*d57664e9SAndroid Build Coastguard Worker 
boolTojboolean(bool value)31*d57664e9SAndroid Build Coastguard Worker static inline jboolean boolTojboolean(bool value) {
32*d57664e9SAndroid Build Coastguard Worker     return value ? JNI_TRUE : JNI_FALSE;
33*d57664e9SAndroid Build Coastguard Worker }
34*d57664e9SAndroid Build Coastguard Worker 
GetSkRegion(JNIEnv * env,jobject regionObject)35*d57664e9SAndroid Build Coastguard Worker static inline SkRegion* GetSkRegion(JNIEnv* env, jobject regionObject) {
36*d57664e9SAndroid Build Coastguard Worker     jlong regionHandle = env->GetLongField(regionObject, gRegion_nativeInstanceFieldID);
37*d57664e9SAndroid Build Coastguard Worker     SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
38*d57664e9SAndroid Build Coastguard Worker     SkASSERT(region != NULL);
39*d57664e9SAndroid Build Coastguard Worker     return region;
40*d57664e9SAndroid Build Coastguard Worker }
41*d57664e9SAndroid Build Coastguard Worker 
Region_constructor(JNIEnv * env,jobject)42*d57664e9SAndroid Build Coastguard Worker static jlong Region_constructor(JNIEnv* env, jobject) {
43*d57664e9SAndroid Build Coastguard Worker     return reinterpret_cast<jlong>(new SkRegion);
44*d57664e9SAndroid Build Coastguard Worker }
45*d57664e9SAndroid Build Coastguard Worker 
Region_destructor(JNIEnv * env,jobject,jlong regionHandle)46*d57664e9SAndroid Build Coastguard Worker static void Region_destructor(JNIEnv* env, jobject, jlong regionHandle) {
47*d57664e9SAndroid Build Coastguard Worker     SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
48*d57664e9SAndroid Build Coastguard Worker     SkASSERT(region);
49*d57664e9SAndroid Build Coastguard Worker     delete region;
50*d57664e9SAndroid Build Coastguard Worker }
51*d57664e9SAndroid Build Coastguard Worker 
Region_setRegion(JNIEnv * env,jobject,jlong dstHandle,jlong srcHandle)52*d57664e9SAndroid Build Coastguard Worker static void Region_setRegion(JNIEnv* env, jobject, jlong dstHandle, jlong srcHandle) {
53*d57664e9SAndroid Build Coastguard Worker     SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
54*d57664e9SAndroid Build Coastguard Worker     const SkRegion* src = reinterpret_cast<SkRegion*>(srcHandle);
55*d57664e9SAndroid Build Coastguard Worker     SkASSERT(dst && src);
56*d57664e9SAndroid Build Coastguard Worker     *dst = *src;
57*d57664e9SAndroid Build Coastguard Worker }
58*d57664e9SAndroid Build Coastguard Worker 
Region_setRect(JNIEnv * env,jobject,jlong dstHandle,jint left,jint top,jint right,jint bottom)59*d57664e9SAndroid Build Coastguard Worker static jboolean Region_setRect(JNIEnv* env, jobject, jlong dstHandle, jint left, jint top, jint right, jint bottom) {
60*d57664e9SAndroid Build Coastguard Worker     SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
61*d57664e9SAndroid Build Coastguard Worker     bool result = dst->setRect({left, top, right, bottom});
62*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
63*d57664e9SAndroid Build Coastguard Worker }
64*d57664e9SAndroid Build Coastguard Worker 
Region_setPath(JNIEnv * env,jobject,jlong dstHandle,jlong pathHandle,jlong clipHandle)65*d57664e9SAndroid Build Coastguard Worker static jboolean Region_setPath(JNIEnv* env, jobject, jlong dstHandle,
66*d57664e9SAndroid Build Coastguard Worker                                jlong pathHandle, jlong clipHandle) {
67*d57664e9SAndroid Build Coastguard Worker     SkRegion*       dst  = reinterpret_cast<SkRegion*>(dstHandle);
68*d57664e9SAndroid Build Coastguard Worker     const SkPath*   path = reinterpret_cast<SkPath*>(pathHandle);
69*d57664e9SAndroid Build Coastguard Worker     const SkRegion* clip = reinterpret_cast<SkRegion*>(clipHandle);
70*d57664e9SAndroid Build Coastguard Worker     SkASSERT(dst && path && clip);
71*d57664e9SAndroid Build Coastguard Worker     bool result = dst->setPath(*path, *clip);
72*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
73*d57664e9SAndroid Build Coastguard Worker 
74*d57664e9SAndroid Build Coastguard Worker }
75*d57664e9SAndroid Build Coastguard Worker 
Region_getBounds(JNIEnv * env,jobject,jlong regionHandle,jobject rectBounds)76*d57664e9SAndroid Build Coastguard Worker static jboolean Region_getBounds(JNIEnv* env, jobject, jlong regionHandle, jobject rectBounds) {
77*d57664e9SAndroid Build Coastguard Worker     SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
78*d57664e9SAndroid Build Coastguard Worker     GraphicsJNI::irect_to_jrect(region->getBounds(), env, rectBounds);
79*d57664e9SAndroid Build Coastguard Worker     bool result = !region->isEmpty();
80*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
81*d57664e9SAndroid Build Coastguard Worker }
82*d57664e9SAndroid Build Coastguard Worker 
Region_getBoundaryPath(JNIEnv * env,jobject,jlong regionHandle,jlong pathHandle)83*d57664e9SAndroid Build Coastguard Worker static jboolean Region_getBoundaryPath(JNIEnv* env, jobject, jlong regionHandle, jlong pathHandle) {
84*d57664e9SAndroid Build Coastguard Worker     const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
85*d57664e9SAndroid Build Coastguard Worker     SkPath*   path = reinterpret_cast<SkPath*>(pathHandle);
86*d57664e9SAndroid Build Coastguard Worker     bool result = region->getBoundaryPath(path);
87*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
88*d57664e9SAndroid Build Coastguard Worker }
89*d57664e9SAndroid Build Coastguard Worker 
Region_op0(JNIEnv * env,jobject,jlong dstHandle,jint left,jint top,jint right,jint bottom,jint op)90*d57664e9SAndroid Build Coastguard Worker static jboolean Region_op0(JNIEnv* env, jobject, jlong dstHandle, jint left, jint top, jint right, jint bottom, jint op) {
91*d57664e9SAndroid Build Coastguard Worker     SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
92*d57664e9SAndroid Build Coastguard Worker     bool result = dst->op({left, top, right, bottom}, (SkRegion::Op)op);
93*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
94*d57664e9SAndroid Build Coastguard Worker }
95*d57664e9SAndroid Build Coastguard Worker 
Region_op1(JNIEnv * env,jobject,jlong dstHandle,jobject rectObject,jlong regionHandle,jint op)96*d57664e9SAndroid Build Coastguard Worker static jboolean Region_op1(JNIEnv* env, jobject, jlong dstHandle, jobject rectObject, jlong regionHandle, jint op) {
97*d57664e9SAndroid Build Coastguard Worker     SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
98*d57664e9SAndroid Build Coastguard Worker     const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
99*d57664e9SAndroid Build Coastguard Worker     SkIRect    ir;
100*d57664e9SAndroid Build Coastguard Worker     GraphicsJNI::jrect_to_irect(env, rectObject, &ir);
101*d57664e9SAndroid Build Coastguard Worker     bool result = dst->op(ir, *region, (SkRegion::Op)op);
102*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
103*d57664e9SAndroid Build Coastguard Worker }
104*d57664e9SAndroid Build Coastguard Worker 
Region_op2(JNIEnv * env,jobject,jlong dstHandle,jlong region1Handle,jlong region2Handle,jint op)105*d57664e9SAndroid Build Coastguard Worker static jboolean Region_op2(JNIEnv* env, jobject, jlong dstHandle, jlong region1Handle, jlong region2Handle, jint op) {
106*d57664e9SAndroid Build Coastguard Worker     SkRegion* dst = reinterpret_cast<SkRegion*>(dstHandle);
107*d57664e9SAndroid Build Coastguard Worker     const SkRegion* region1 = reinterpret_cast<SkRegion*>(region1Handle);
108*d57664e9SAndroid Build Coastguard Worker     const SkRegion* region2 = reinterpret_cast<SkRegion*>(region2Handle);
109*d57664e9SAndroid Build Coastguard Worker     bool result = dst->op(*region1, *region2, (SkRegion::Op)op);
110*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
111*d57664e9SAndroid Build Coastguard Worker }
112*d57664e9SAndroid Build Coastguard Worker 
113*d57664e9SAndroid Build Coastguard Worker ////////////////////////////////////  These are methods, not static
114*d57664e9SAndroid Build Coastguard Worker 
Region_isEmpty(JNIEnv * env,jobject region)115*d57664e9SAndroid Build Coastguard Worker static jboolean Region_isEmpty(JNIEnv* env, jobject region) {
116*d57664e9SAndroid Build Coastguard Worker     bool result = GetSkRegion(env, region)->isEmpty();
117*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
118*d57664e9SAndroid Build Coastguard Worker }
119*d57664e9SAndroid Build Coastguard Worker 
Region_isRect(JNIEnv * env,jobject region)120*d57664e9SAndroid Build Coastguard Worker static jboolean Region_isRect(JNIEnv* env, jobject region) {
121*d57664e9SAndroid Build Coastguard Worker     bool result = GetSkRegion(env, region)->isRect();
122*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
123*d57664e9SAndroid Build Coastguard Worker }
124*d57664e9SAndroid Build Coastguard Worker 
Region_isComplex(JNIEnv * env,jobject region)125*d57664e9SAndroid Build Coastguard Worker static jboolean Region_isComplex(JNIEnv* env, jobject region) {
126*d57664e9SAndroid Build Coastguard Worker     bool result = GetSkRegion(env, region)->isComplex();
127*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
128*d57664e9SAndroid Build Coastguard Worker }
129*d57664e9SAndroid Build Coastguard Worker 
Region_contains(JNIEnv * env,jobject region,jint x,jint y)130*d57664e9SAndroid Build Coastguard Worker static jboolean Region_contains(JNIEnv* env, jobject region, jint x, jint y) {
131*d57664e9SAndroid Build Coastguard Worker     bool result = GetSkRegion(env, region)->contains(x, y);
132*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
133*d57664e9SAndroid Build Coastguard Worker }
134*d57664e9SAndroid Build Coastguard Worker 
Region_quickContains(JNIEnv * env,jobject region,jint left,jint top,jint right,jint bottom)135*d57664e9SAndroid Build Coastguard Worker static jboolean Region_quickContains(JNIEnv* env, jobject region, jint left, jint top, jint right, jint bottom) {
136*d57664e9SAndroid Build Coastguard Worker     bool result = GetSkRegion(env, region)->quickContains({left, top, right, bottom});
137*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
138*d57664e9SAndroid Build Coastguard Worker }
139*d57664e9SAndroid Build Coastguard Worker 
Region_quickRejectIIII(JNIEnv * env,jobject region,jint left,jint top,jint right,jint bottom)140*d57664e9SAndroid Build Coastguard Worker static jboolean Region_quickRejectIIII(JNIEnv* env, jobject region, jint left, jint top, jint right, jint bottom) {
141*d57664e9SAndroid Build Coastguard Worker     SkIRect ir;
142*d57664e9SAndroid Build Coastguard Worker     ir.setLTRB(left, top, right, bottom);
143*d57664e9SAndroid Build Coastguard Worker     bool result = GetSkRegion(env, region)->quickReject(ir);
144*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
145*d57664e9SAndroid Build Coastguard Worker }
146*d57664e9SAndroid Build Coastguard Worker 
Region_quickRejectRgn(JNIEnv * env,jobject region,jobject other)147*d57664e9SAndroid Build Coastguard Worker static jboolean Region_quickRejectRgn(JNIEnv* env, jobject region, jobject other) {
148*d57664e9SAndroid Build Coastguard Worker     bool result = GetSkRegion(env, region)->quickReject(*GetSkRegion(env, other));
149*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(result);
150*d57664e9SAndroid Build Coastguard Worker }
151*d57664e9SAndroid Build Coastguard Worker 
Region_translate(JNIEnv * env,jobject region,jint x,jint y,jobject dst)152*d57664e9SAndroid Build Coastguard Worker static void Region_translate(JNIEnv* env, jobject region, jint x, jint y, jobject dst) {
153*d57664e9SAndroid Build Coastguard Worker     SkRegion* rgn = GetSkRegion(env, region);
154*d57664e9SAndroid Build Coastguard Worker     if (dst)
155*d57664e9SAndroid Build Coastguard Worker         rgn->translate(x, y, GetSkRegion(env, dst));
156*d57664e9SAndroid Build Coastguard Worker     else
157*d57664e9SAndroid Build Coastguard Worker         rgn->translate(x, y);
158*d57664e9SAndroid Build Coastguard Worker }
159*d57664e9SAndroid Build Coastguard Worker 
160*d57664e9SAndroid Build Coastguard Worker // Scale the rectangle by given scale and set the reuslt to the dst.
scale_rect(SkIRect * dst,const SkIRect & src,float scale)161*d57664e9SAndroid Build Coastguard Worker static void scale_rect(SkIRect* dst, const SkIRect& src, float scale) {
162*d57664e9SAndroid Build Coastguard Worker    dst->fLeft = (int)::roundf(src.fLeft * scale);
163*d57664e9SAndroid Build Coastguard Worker    dst->fTop = (int)::roundf(src.fTop * scale);
164*d57664e9SAndroid Build Coastguard Worker    dst->fRight = (int)::roundf(src.fRight * scale);
165*d57664e9SAndroid Build Coastguard Worker    dst->fBottom = (int)::roundf(src.fBottom * scale);
166*d57664e9SAndroid Build Coastguard Worker }
167*d57664e9SAndroid Build Coastguard Worker 
168*d57664e9SAndroid Build Coastguard Worker // Scale the region by given scale and set the reuslt to the dst.
169*d57664e9SAndroid Build Coastguard Worker // dest and src can be the same region instance.
scale_rgn(SkRegion * dst,const SkRegion & src,float scale)170*d57664e9SAndroid Build Coastguard Worker static void scale_rgn(SkRegion* dst, const SkRegion& src, float scale) {
171*d57664e9SAndroid Build Coastguard Worker    SkRegion tmp;
172*d57664e9SAndroid Build Coastguard Worker    SkRegion::Iterator iter(src);
173*d57664e9SAndroid Build Coastguard Worker 
174*d57664e9SAndroid Build Coastguard Worker    for (; !iter.done(); iter.next()) {
175*d57664e9SAndroid Build Coastguard Worker        SkIRect r;
176*d57664e9SAndroid Build Coastguard Worker        scale_rect(&r, iter.rect(), scale);
177*d57664e9SAndroid Build Coastguard Worker        tmp.op(r, SkRegion::kUnion_Op);
178*d57664e9SAndroid Build Coastguard Worker    }
179*d57664e9SAndroid Build Coastguard Worker    dst->swap(tmp);
180*d57664e9SAndroid Build Coastguard Worker }
181*d57664e9SAndroid Build Coastguard Worker 
Region_scale(JNIEnv * env,jobject region,jfloat scale,jobject dst)182*d57664e9SAndroid Build Coastguard Worker static void Region_scale(JNIEnv* env, jobject region, jfloat scale, jobject dst) {
183*d57664e9SAndroid Build Coastguard Worker     SkRegion* rgn = GetSkRegion(env, region);
184*d57664e9SAndroid Build Coastguard Worker     if (dst)
185*d57664e9SAndroid Build Coastguard Worker         scale_rgn(GetSkRegion(env, dst), *rgn, scale);
186*d57664e9SAndroid Build Coastguard Worker     else
187*d57664e9SAndroid Build Coastguard Worker         scale_rgn(rgn, *rgn, scale);
188*d57664e9SAndroid Build Coastguard Worker }
189*d57664e9SAndroid Build Coastguard Worker 
Region_toString(JNIEnv * env,jobject clazz,jlong regionHandle)190*d57664e9SAndroid Build Coastguard Worker static jstring Region_toString(JNIEnv* env, jobject clazz, jlong regionHandle) {
191*d57664e9SAndroid Build Coastguard Worker     SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
192*d57664e9SAndroid Build Coastguard Worker     char* str = region->toString();
193*d57664e9SAndroid Build Coastguard Worker     if (str == NULL) {
194*d57664e9SAndroid Build Coastguard Worker         return NULL;
195*d57664e9SAndroid Build Coastguard Worker     }
196*d57664e9SAndroid Build Coastguard Worker     jstring result = env->NewStringUTF(str);
197*d57664e9SAndroid Build Coastguard Worker     free(str);
198*d57664e9SAndroid Build Coastguard Worker     return result;
199*d57664e9SAndroid Build Coastguard Worker }
200*d57664e9SAndroid Build Coastguard Worker 
201*d57664e9SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////////////
202*d57664e9SAndroid Build Coastguard Worker 
Region_createFromParcel(JNIEnv * env,jobject clazz,jobject parcel)203*d57664e9SAndroid Build Coastguard Worker static jlong Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel)
204*d57664e9SAndroid Build Coastguard Worker {
205*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__ // Layoutlib does not support parcel
206*d57664e9SAndroid Build Coastguard Worker     if (parcel == nullptr) {
207*d57664e9SAndroid Build Coastguard Worker         return 0;
208*d57664e9SAndroid Build Coastguard Worker     }
209*d57664e9SAndroid Build Coastguard Worker 
210*d57664e9SAndroid Build Coastguard Worker     std::vector<int32_t> rects;
211*d57664e9SAndroid Build Coastguard Worker 
212*d57664e9SAndroid Build Coastguard Worker     AParcel* p = AParcel_fromJavaParcel(env, parcel);
213*d57664e9SAndroid Build Coastguard Worker     ndk::AParcel_readVector(p, &rects);
214*d57664e9SAndroid Build Coastguard Worker     AParcel_delete(p);
215*d57664e9SAndroid Build Coastguard Worker 
216*d57664e9SAndroid Build Coastguard Worker     if ((rects.size() % 4) != 0) {
217*d57664e9SAndroid Build Coastguard Worker         return 0;
218*d57664e9SAndroid Build Coastguard Worker     }
219*d57664e9SAndroid Build Coastguard Worker 
220*d57664e9SAndroid Build Coastguard Worker     SkRegion* region = new SkRegion;
221*d57664e9SAndroid Build Coastguard Worker     for (size_t x = 0; x + 4 <= rects.size(); x += 4) {
222*d57664e9SAndroid Build Coastguard Worker         region->op({rects[x], rects[x+1], rects[x+2], rects[x+3]}, SkRegion::kUnion_Op);
223*d57664e9SAndroid Build Coastguard Worker     }
224*d57664e9SAndroid Build Coastguard Worker 
225*d57664e9SAndroid Build Coastguard Worker     return reinterpret_cast<jlong>(region);
226*d57664e9SAndroid Build Coastguard Worker #else
227*d57664e9SAndroid Build Coastguard Worker     return 0;
228*d57664e9SAndroid Build Coastguard Worker #endif
229*d57664e9SAndroid Build Coastguard Worker }
230*d57664e9SAndroid Build Coastguard Worker 
Region_writeToParcel(JNIEnv * env,jobject clazz,jlong regionHandle,jobject parcel)231*d57664e9SAndroid Build Coastguard Worker static jboolean Region_writeToParcel(JNIEnv* env, jobject clazz, jlong regionHandle, jobject parcel)
232*d57664e9SAndroid Build Coastguard Worker {
233*d57664e9SAndroid Build Coastguard Worker #ifdef __ANDROID__ // Layoutlib does not support parcel
234*d57664e9SAndroid Build Coastguard Worker     const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
235*d57664e9SAndroid Build Coastguard Worker     if (parcel == nullptr) {
236*d57664e9SAndroid Build Coastguard Worker         return JNI_FALSE;
237*d57664e9SAndroid Build Coastguard Worker     }
238*d57664e9SAndroid Build Coastguard Worker 
239*d57664e9SAndroid Build Coastguard Worker     std::vector<int32_t> rects;
240*d57664e9SAndroid Build Coastguard Worker     SkRegion::Iterator it(*region);
241*d57664e9SAndroid Build Coastguard Worker     while (!it.done()) {
242*d57664e9SAndroid Build Coastguard Worker         const SkIRect& r = it.rect();
243*d57664e9SAndroid Build Coastguard Worker         rects.push_back(r.fLeft);
244*d57664e9SAndroid Build Coastguard Worker         rects.push_back(r.fTop);
245*d57664e9SAndroid Build Coastguard Worker         rects.push_back(r.fRight);
246*d57664e9SAndroid Build Coastguard Worker         rects.push_back(r.fBottom);
247*d57664e9SAndroid Build Coastguard Worker         it.next();
248*d57664e9SAndroid Build Coastguard Worker     }
249*d57664e9SAndroid Build Coastguard Worker 
250*d57664e9SAndroid Build Coastguard Worker     AParcel* p = AParcel_fromJavaParcel(env, parcel);
251*d57664e9SAndroid Build Coastguard Worker     ndk::AParcel_writeVector(p, rects);
252*d57664e9SAndroid Build Coastguard Worker     AParcel_delete(p);
253*d57664e9SAndroid Build Coastguard Worker 
254*d57664e9SAndroid Build Coastguard Worker     return JNI_TRUE;
255*d57664e9SAndroid Build Coastguard Worker #else
256*d57664e9SAndroid Build Coastguard Worker     return JNI_FALSE;
257*d57664e9SAndroid Build Coastguard Worker #endif
258*d57664e9SAndroid Build Coastguard Worker }
259*d57664e9SAndroid Build Coastguard Worker 
260*d57664e9SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////////////
261*d57664e9SAndroid Build Coastguard Worker 
Region_equals(JNIEnv * env,jobject clazz,jlong r1Handle,jlong r2Handle)262*d57664e9SAndroid Build Coastguard Worker static jboolean Region_equals(JNIEnv* env, jobject clazz, jlong r1Handle, jlong r2Handle)
263*d57664e9SAndroid Build Coastguard Worker {
264*d57664e9SAndroid Build Coastguard Worker     const SkRegion *r1 = reinterpret_cast<SkRegion*>(r1Handle);
265*d57664e9SAndroid Build Coastguard Worker     const SkRegion *r2 = reinterpret_cast<SkRegion*>(r2Handle);
266*d57664e9SAndroid Build Coastguard Worker     return boolTojboolean(*r1 == *r2);
267*d57664e9SAndroid Build Coastguard Worker }
268*d57664e9SAndroid Build Coastguard Worker 
269*d57664e9SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////////////
270*d57664e9SAndroid Build Coastguard Worker 
271*d57664e9SAndroid Build Coastguard Worker struct RgnIterPair {
272*d57664e9SAndroid Build Coastguard Worker     SkRegion            fRgn;   // a copy of the caller's region
273*d57664e9SAndroid Build Coastguard Worker     SkRegion::Iterator  fIter;  // an iterator acting upon the copy (fRgn)
274*d57664e9SAndroid Build Coastguard Worker 
RgnIterPairandroid::RgnIterPair275*d57664e9SAndroid Build Coastguard Worker     explicit RgnIterPair(const SkRegion& rgn) : fRgn(rgn) {
276*d57664e9SAndroid Build Coastguard Worker         // have our iterator reference our copy (fRgn), so we know it will be
277*d57664e9SAndroid Build Coastguard Worker         // unchanged for the lifetime of the iterator
278*d57664e9SAndroid Build Coastguard Worker         fIter.reset(fRgn);
279*d57664e9SAndroid Build Coastguard Worker     }
280*d57664e9SAndroid Build Coastguard Worker };
281*d57664e9SAndroid Build Coastguard Worker 
RegionIter_constructor(JNIEnv * env,jobject,jlong regionHandle)282*d57664e9SAndroid Build Coastguard Worker static jlong RegionIter_constructor(JNIEnv* env, jobject, jlong regionHandle)
283*d57664e9SAndroid Build Coastguard Worker {
284*d57664e9SAndroid Build Coastguard Worker     const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle);
285*d57664e9SAndroid Build Coastguard Worker     SkASSERT(region);
286*d57664e9SAndroid Build Coastguard Worker     return reinterpret_cast<jlong>(new RgnIterPair(*region));
287*d57664e9SAndroid Build Coastguard Worker }
288*d57664e9SAndroid Build Coastguard Worker 
RegionIter_destructor(JNIEnv * env,jobject,jlong pairHandle)289*d57664e9SAndroid Build Coastguard Worker static void RegionIter_destructor(JNIEnv* env, jobject, jlong pairHandle)
290*d57664e9SAndroid Build Coastguard Worker {
291*d57664e9SAndroid Build Coastguard Worker     RgnIterPair* pair = reinterpret_cast<RgnIterPair*>(pairHandle);
292*d57664e9SAndroid Build Coastguard Worker     SkASSERT(pair);
293*d57664e9SAndroid Build Coastguard Worker     delete pair;
294*d57664e9SAndroid Build Coastguard Worker }
295*d57664e9SAndroid Build Coastguard Worker 
RegionIter_next(JNIEnv * env,jobject,jlong pairHandle,jobject rectObject)296*d57664e9SAndroid Build Coastguard Worker static jboolean RegionIter_next(JNIEnv* env, jobject, jlong pairHandle, jobject rectObject)
297*d57664e9SAndroid Build Coastguard Worker {
298*d57664e9SAndroid Build Coastguard Worker     RgnIterPair* pair = reinterpret_cast<RgnIterPair*>(pairHandle);
299*d57664e9SAndroid Build Coastguard Worker     // the caller has checked that rectObject is not nul
300*d57664e9SAndroid Build Coastguard Worker     SkASSERT(pair);
301*d57664e9SAndroid Build Coastguard Worker     SkASSERT(rectObject);
302*d57664e9SAndroid Build Coastguard Worker 
303*d57664e9SAndroid Build Coastguard Worker     if (!pair->fIter.done()) {
304*d57664e9SAndroid Build Coastguard Worker         GraphicsJNI::irect_to_jrect(pair->fIter.rect(), env, rectObject);
305*d57664e9SAndroid Build Coastguard Worker         pair->fIter.next();
306*d57664e9SAndroid Build Coastguard Worker         return JNI_TRUE;
307*d57664e9SAndroid Build Coastguard Worker     }
308*d57664e9SAndroid Build Coastguard Worker     return JNI_FALSE;
309*d57664e9SAndroid Build Coastguard Worker }
310*d57664e9SAndroid Build Coastguard Worker 
311*d57664e9SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////////////////////////////////
312*d57664e9SAndroid Build Coastguard Worker 
313*d57664e9SAndroid Build Coastguard Worker static const JNINativeMethod gRegionIterMethods[] = {
314*d57664e9SAndroid Build Coastguard Worker     { "nativeConstructor",  "(J)J",                         (void*)RegionIter_constructor   },
315*d57664e9SAndroid Build Coastguard Worker     { "nativeDestructor",   "(J)V",                         (void*)RegionIter_destructor    },
316*d57664e9SAndroid Build Coastguard Worker     { "nativeNext",         "(JLandroid/graphics/Rect;)Z",  (void*)RegionIter_next          }
317*d57664e9SAndroid Build Coastguard Worker };
318*d57664e9SAndroid Build Coastguard Worker 
319*d57664e9SAndroid Build Coastguard Worker static const JNINativeMethod gRegionMethods[] = {
320*d57664e9SAndroid Build Coastguard Worker     // these are static methods
321*d57664e9SAndroid Build Coastguard Worker     { "nativeConstructor",      "()J",                              (void*)Region_constructor       },
322*d57664e9SAndroid Build Coastguard Worker     { "nativeDestructor",       "(J)V",                             (void*)Region_destructor        },
323*d57664e9SAndroid Build Coastguard Worker     { "nativeSetRegion",        "(JJ)V",                            (void*)Region_setRegion         },
324*d57664e9SAndroid Build Coastguard Worker     { "nativeSetRect",          "(JIIII)Z",                         (void*)Region_setRect           },
325*d57664e9SAndroid Build Coastguard Worker     { "nativeSetPath",          "(JJJ)Z",                           (void*)Region_setPath           },
326*d57664e9SAndroid Build Coastguard Worker     { "nativeGetBounds",        "(JLandroid/graphics/Rect;)Z",      (void*)Region_getBounds         },
327*d57664e9SAndroid Build Coastguard Worker     { "nativeGetBoundaryPath",  "(JJ)Z",                            (void*)Region_getBoundaryPath   },
328*d57664e9SAndroid Build Coastguard Worker     { "nativeOp",               "(JIIIII)Z",                        (void*)Region_op0               },
329*d57664e9SAndroid Build Coastguard Worker     { "nativeOp",               "(JLandroid/graphics/Rect;JI)Z",    (void*)Region_op1               },
330*d57664e9SAndroid Build Coastguard Worker     { "nativeOp",               "(JJJI)Z",                          (void*)Region_op2               },
331*d57664e9SAndroid Build Coastguard Worker     // these are methods that take the java region object
332*d57664e9SAndroid Build Coastguard Worker     { "isEmpty",                "()Z",                              (void*)Region_isEmpty           },
333*d57664e9SAndroid Build Coastguard Worker     { "isRect",                 "()Z",                              (void*)Region_isRect            },
334*d57664e9SAndroid Build Coastguard Worker     { "isComplex",              "()Z",                              (void*)Region_isComplex         },
335*d57664e9SAndroid Build Coastguard Worker     { "contains",               "(II)Z",                            (void*)Region_contains          },
336*d57664e9SAndroid Build Coastguard Worker     { "quickContains",          "(IIII)Z",                          (void*)Region_quickContains     },
337*d57664e9SAndroid Build Coastguard Worker     { "quickReject",            "(IIII)Z",                          (void*)Region_quickRejectIIII   },
338*d57664e9SAndroid Build Coastguard Worker     { "quickReject",            "(Landroid/graphics/Region;)Z",     (void*)Region_quickRejectRgn    },
339*d57664e9SAndroid Build Coastguard Worker     { "scale",                  "(FLandroid/graphics/Region;)V",    (void*)Region_scale             },
340*d57664e9SAndroid Build Coastguard Worker     { "translate",              "(IILandroid/graphics/Region;)V",   (void*)Region_translate         },
341*d57664e9SAndroid Build Coastguard Worker     { "nativeToString",         "(J)Ljava/lang/String;",            (void*)Region_toString          },
342*d57664e9SAndroid Build Coastguard Worker     // parceling methods
343*d57664e9SAndroid Build Coastguard Worker     { "nativeCreateFromParcel", "(Landroid/os/Parcel;)J",           (void*)Region_createFromParcel  },
344*d57664e9SAndroid Build Coastguard Worker     { "nativeWriteToParcel",    "(JLandroid/os/Parcel;)Z",          (void*)Region_writeToParcel     },
345*d57664e9SAndroid Build Coastguard Worker     { "nativeEquals",           "(JJ)Z",                            (void*)Region_equals            },
346*d57664e9SAndroid Build Coastguard Worker };
347*d57664e9SAndroid Build Coastguard Worker 
register_android_graphics_Region(JNIEnv * env)348*d57664e9SAndroid Build Coastguard Worker int register_android_graphics_Region(JNIEnv* env)
349*d57664e9SAndroid Build Coastguard Worker {
350*d57664e9SAndroid Build Coastguard Worker     jclass clazz = FindClassOrDie(env, "android/graphics/Region");
351*d57664e9SAndroid Build Coastguard Worker 
352*d57664e9SAndroid Build Coastguard Worker     gRegion_nativeInstanceFieldID = GetFieldIDOrDie(env, clazz, "mNativeRegion", "J");
353*d57664e9SAndroid Build Coastguard Worker 
354*d57664e9SAndroid Build Coastguard Worker     RegisterMethodsOrDie(env, "android/graphics/Region", gRegionMethods, NELEM(gRegionMethods));
355*d57664e9SAndroid Build Coastguard Worker     return RegisterMethodsOrDie(env, "android/graphics/RegionIterator", gRegionIterMethods,
356*d57664e9SAndroid Build Coastguard Worker                                 NELEM(gRegionIterMethods));
357*d57664e9SAndroid Build Coastguard Worker }
358*d57664e9SAndroid Build Coastguard Worker 
359*d57664e9SAndroid Build Coastguard Worker } // namespace android
360