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 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 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