1 | /* |
2 | * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this |
8 | * particular file as subject to the "Classpath" exception as provided |
9 | * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 | * or visit www.oracle.com if you need additional information or have any |
23 | * 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 | |
33 | static void |
34 | RefineBounds(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 | |
61 | static void |
62 | ProcessPoly(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 | */ |
107 | JNIEXPORT void JNICALL |
108 | Java_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 | if (!xPointsPtr) { |
190 | ok = JNI_FALSE; |
191 | } |
192 | if (ok) { |
193 | yPointsPtr = (*env)->GetPrimitiveArrayCritical(env, yPointsArray, NULL); |
194 | if (!yPointsPtr) { |
195 | ok = JNI_FALSE; |
196 | } |
197 | } |
198 | } |
199 | |
200 | if (ok) { |
201 | if (ret == SD_SLOWLOCK) { |
202 | RefineBounds(&rasInfo.bounds, transX, transY, |
203 | xPointsPtr, yPointsPtr, pointsNeeded); |
204 | ok = (rasInfo.bounds.x2 > rasInfo.bounds.x1 && |
205 | rasInfo.bounds.y2 > rasInfo.bounds.y1); |
206 | } |
207 | } |
208 | |
209 | if (ok) { |
210 | sdOps->GetRasInfo(env, sdOps, &rasInfo); |
211 | if (rasInfo.rasBase && |
212 | rasInfo.bounds.x2 > rasInfo.bounds.x1 && |
213 | rasInfo.bounds.y2 > rasInfo.bounds.y1) |
214 | { |
215 | ProcessPoly(&rasInfo, pPrim->funcs.drawline, pPrim, &compInfo, |
216 | pixel, transX, transY, |
217 | xPointsPtr, yPointsPtr, |
218 | nPointsPtr, numPolys, |
219 | close); |
220 | } |
221 | SurfaceData_InvokeRelease(env, sdOps, &rasInfo); |
222 | } |
223 | |
224 | if (nPointsPtr) { |
225 | (*env)->ReleasePrimitiveArrayCritical(env, nPointsArray, |
226 | nPointsPtr, JNI_ABORT); |
227 | } |
228 | if (xPointsPtr) { |
229 | (*env)->ReleasePrimitiveArrayCritical(env, xPointsArray, |
230 | xPointsPtr, JNI_ABORT); |
231 | } |
232 | if (yPointsPtr) { |
233 | (*env)->ReleasePrimitiveArrayCritical(env, yPointsArray, |
234 | yPointsPtr, JNI_ABORT); |
235 | } |
236 | SurfaceData_InvokeUnlock(env, sdOps, &rasInfo); |
237 | } |
238 | |