blob: a557ef73f7ac4484e7528c1f5b93d6087842ab45 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2002 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include "jni_util.h"
27
28#include "GraphicsPrimitiveMgr.h"
29#include "LineUtils.h"
30
31#include "sun_java2d_loops_DrawPolygons.h"
32
33static void
34RefineBounds(SurfaceDataBounds *bounds, jint transX, jint transY,
35 jint *xPointsPtr, jint *yPointsPtr, jint pointsNeeded)
36{
37 jint xmin, ymin, xmax, ymax;
38 if (pointsNeeded > 0) {
39 xmin = xmax = transX + *xPointsPtr++;
40 ymin = ymax = transY + *yPointsPtr++;
41 while (--pointsNeeded > 0) {
42 jint x = transX + *xPointsPtr++;
43 jint y = transY + *yPointsPtr++;
44 if (xmin > x) xmin = x;
45 if (ymin > y) ymin = y;
46 if (xmax < x) xmax = x;
47 if (ymax < y) ymax = y;
48 }
49 if (++xmax < xmin) xmax--;
50 if (++ymax < ymin) ymax--;
51 if (bounds->x1 < xmin) bounds->x1 = xmin;
52 if (bounds->y1 < ymin) bounds->y1 = ymin;
53 if (bounds->x2 > xmax) bounds->x2 = xmax;
54 if (bounds->y2 > ymax) bounds->y2 = ymax;
55 } else {
56 bounds->x2 = bounds->x1;
57 bounds->y2 = bounds->y1;
58 }
59}
60
61static void
62ProcessPoly(SurfaceDataRasInfo *pRasInfo,
63 DrawLineFunc *pLine,
64 NativePrimitive *pPrim,
65 CompositeInfo *pCompInfo,
66 jint pixel, jint transX, jint transY,
67 jint *xPointsPtr, jint *yPointsPtr,
68 jint *nPointsPtr, jint numPolys,
69 jboolean close)
70{
71 int i;
72 for (i = 0; i < numPolys; i++) {
73 jint numPts = nPointsPtr[i];
74 if (numPts > 1) {
75 jint x0, y0, x1, y1;
76 jboolean empty = JNI_TRUE;
77 x0 = x1 = transX + *xPointsPtr++;
78 y0 = y1 = transY + *yPointsPtr++;
79 while (--numPts > 0) {
80 jint x2 = transX + *xPointsPtr++;
81 jint y2 = transY + *yPointsPtr++;
82 empty = (empty && x1 == x2 && y1 == y2);
83 LineUtils_ProcessLine(pRasInfo, pixel, pLine,
84 pPrim, pCompInfo,
85 x1, y1, x2, y2,
86 (numPts > 1 || close));
87 x1 = x2;
88 y1 = y2;
89 }
90 if (close && (empty || x1 != x0 || y1 != y0)) {
91 LineUtils_ProcessLine(pRasInfo, pixel, pLine,
92 pPrim, pCompInfo,
93 x1, y1, x0, y0, !empty);
94 }
95 } else if (numPts == 1) {
96 xPointsPtr++;
97 yPointsPtr++;
98 }
99 }
100}
101
102/*
103 * Class: sun_java2d_loops_DrawPolygons
104 * Method: DrawPolygons
105 * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;[I[I[IIIIZ)V
106 */
107JNIEXPORT void JNICALL
108Java_sun_java2d_loops_DrawPolygons_DrawPolygons
109 (JNIEnv *env, jobject self,
110 jobject sg2d, jobject sData,
111 jintArray xPointsArray, jintArray yPointsArray,
112 jintArray nPointsArray, jint numPolys,
113 jint transX, jint transY, jboolean close)
114{
115 SurfaceDataOps *sdOps;
116 SurfaceDataRasInfo rasInfo;
117 NativePrimitive *pPrim;
118 CompositeInfo compInfo;
119 jsize nPointsLen, xPointsLen, yPointsLen;
120 jint *nPointsPtr = NULL;
121 jint *xPointsPtr = NULL;
122 jint *yPointsPtr = NULL;
123 jint pointsNeeded;
124 jint i, ret;
125 jboolean ok = JNI_TRUE;
126 jint pixel = GrPrim_Sg2dGetPixel(env, sg2d);
127
128 if (JNU_IsNull(env, xPointsArray) || JNU_IsNull(env, yPointsArray)) {
129 JNU_ThrowNullPointerException(env, "coordinate array");
130 return;
131 }
132 if (JNU_IsNull(env, nPointsArray)) {
133 JNU_ThrowNullPointerException(env, "polygon length array");
134 return;
135 }
136
137 nPointsLen = (*env)->GetArrayLength(env, nPointsArray);
138 xPointsLen = (*env)->GetArrayLength(env, xPointsArray);
139 yPointsLen = (*env)->GetArrayLength(env, yPointsArray);
140 if (nPointsLen < numPolys) {
141 JNU_ThrowArrayIndexOutOfBoundsException(env,
142 "polygon length array size");
143 return;
144 }
145
146 pPrim = GetNativePrim(env, self);
147 if (pPrim == NULL) {
148 return;
149 }
150 if (pPrim->pCompType->getCompInfo != NULL) {
151 GrPrim_Sg2dGetCompInfo(env, sg2d, pPrim, &compInfo);
152 }
153
154 sdOps = SurfaceData_GetOps(env, sData);
155 if (sdOps == 0) {
156 return;
157 }
158
159 GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
160
161 ret = sdOps->Lock(env, sdOps, &rasInfo, SD_LOCK_FASTEST | pPrim->dstflags);
162 if (ret == SD_FAILURE) {
163 return;
164 }
165
166 nPointsPtr = (*env)->GetPrimitiveArrayCritical(env, nPointsArray, NULL);
167 if (!nPointsPtr) {
168 ok = JNI_FALSE;
169 }
170
171 if (ok) {
172 pointsNeeded = 0;
173 for (i = 0; i < numPolys; i++) {
174 if (nPointsPtr[i] > 0) {
175 pointsNeeded += nPointsPtr[i];
176 }
177 }
178
179 if (yPointsLen < pointsNeeded || xPointsLen < pointsNeeded) {
180 (*env)->ReleasePrimitiveArrayCritical(env, nPointsArray,
181 nPointsPtr, JNI_ABORT);
182 SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
183 JNU_ThrowArrayIndexOutOfBoundsException(env,
184 "coordinate array length");
185 return;
186 }
187
188 xPointsPtr = (*env)->GetPrimitiveArrayCritical(env, xPointsArray, NULL);
189 yPointsPtr = (*env)->GetPrimitiveArrayCritical(env, yPointsArray, NULL);
190 if (!xPointsPtr || !yPointsPtr) {
191 ok = JNI_FALSE;
192 }
193 }
194
195 if (ok) {
196 if (ret == SD_SLOWLOCK) {
197 RefineBounds(&rasInfo.bounds, transX, transY,
198 xPointsPtr, yPointsPtr, pointsNeeded);
199 ok = (rasInfo.bounds.x2 > rasInfo.bounds.x1 &&
200 rasInfo.bounds.y2 > rasInfo.bounds.y1);
201 }
202 }
203
204 if (ok) {
205 sdOps->GetRasInfo(env, sdOps, &rasInfo);
206 if (rasInfo.rasBase &&
207 rasInfo.bounds.x2 > rasInfo.bounds.x1 &&
208 rasInfo.bounds.y2 > rasInfo.bounds.y1)
209 {
210 ProcessPoly(&rasInfo, pPrim->funcs.drawline, pPrim, &compInfo,
211 pixel, transX, transY,
212 xPointsPtr, yPointsPtr,
213 nPointsPtr, numPolys,
214 close);
215 }
216 SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
217 }
218
219 if (nPointsPtr) {
220 (*env)->ReleasePrimitiveArrayCritical(env, nPointsArray,
221 nPointsPtr, JNI_ABORT);
222 }
223 if (xPointsPtr) {
224 (*env)->ReleasePrimitiveArrayCritical(env, xPointsArray,
225 xPointsPtr, JNI_ABORT);
226 }
227 if (yPointsPtr) {
228 (*env)->ReleasePrimitiveArrayCritical(env, yPointsArray,
229 yPointsPtr, JNI_ABORT);
230 }
231 SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
232}