1 /*
2  * Copyright (c) 2005, 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 <math.h>
27 #include <float.h>
28 #include "jni_util.h"
29 
30 #include "GraphicsPrimitiveMgr.h"
31 #include "LineUtils.h"
32 #include "ProcessPath.h"
33 #include "DrawPath.h"
34 
35 #include "sun_java2d_loops_FillPath.h"
36 
drawScanline(DrawHandler * hnd,jint x0,jint x1,jint y0)37 static void drawScanline(DrawHandler* hnd, jint x0, jint x1, jint y0) {
38     DHND(hnd)->pPrim->funcs.drawline(
39         DHND(hnd)->pRasInfo, x0, y0, DHND(hnd)->pixel, x1 - x0 + 1, 0,
40         BUMP_POS_PIXEL, 0, BUMP_NOOP, 0,
41         DHND(hnd)->pPrim, DHND(hnd)->pCompInfo);
42 }
43 
44 /*
45  * Class:     sun_java2d_loops_FillPath
46  * Method:    FillPath
47  * Signature: (Lsun/java2d/SunGraphics2D;Lsun/java2d/SurfaceData;IILjava/awt/geom/Path2D.Float;)V
48  */
Java_sun_java2d_loops_FillPath_FillPath(JNIEnv * env,jobject self,jobject sg2d,jobject sData,jint transX,jint transY,jobject p2df)49 JNIEXPORT void JNICALL Java_sun_java2d_loops_FillPath_FillPath
50     (JNIEnv *env, jobject self,
51      jobject sg2d, jobject sData,
52      jint transX, jint transY, jobject p2df)
53 {
54     jarray typesArray;
55     jarray coordsArray;
56     jint numTypes;
57     jint fillRule;
58     jboolean ok = JNI_TRUE;
59     jint pixel = GrPrim_Sg2dGetPixel(env, sg2d);
60     jint maxCoords;
61     jfloat *coords;
62     SurfaceDataOps *sdOps;
63     SurfaceDataRasInfo rasInfo;
64     CompositeInfo compInfo;
65     jint ret;
66     NativePrimitive *pPrim = GetNativePrim(env, self);
67     jint stroke;
68     jboolean throwExc = JNI_FALSE;
69 
70     if (pPrim == NULL) {
71         return;
72     }
73     if (pPrim->pCompType->getCompInfo != NULL) {
74         GrPrim_Sg2dGetCompInfo(env, sg2d, pPrim, &compInfo);
75     }
76 
77     stroke = (*env)->GetIntField(env, sg2d, sg2dStrokeHintID);
78 
79     sdOps = SurfaceData_GetOps(env, sData);
80     if (sdOps == 0) {
81         return;
82     }
83 
84     typesArray = (jarray)(*env)->GetObjectField(env, p2df, path2DTypesID);
85     coordsArray = (jarray)(*env)->GetObjectField(env, p2df,
86                                                  path2DFloatCoordsID);
87     if (coordsArray == NULL) {
88         JNU_ThrowNullPointerException(env, "coordinates array");
89         return;
90     }
91     numTypes = (*env)->GetIntField(env, p2df, path2DNumTypesID);
92     fillRule = (*env)->GetIntField(env, p2df, path2DWindingRuleID);
93     if ((*env)->GetArrayLength(env, typesArray) < numTypes) {
94         JNU_ThrowArrayIndexOutOfBoundsException(env, "types array");
95         return;
96     }
97 
98     GrPrim_Sg2dGetClip(env, sg2d, &rasInfo.bounds);
99 
100     ret = sdOps->Lock(env, sdOps, &rasInfo, SD_LOCK_FASTEST | pPrim->dstflags);
101     if (ret == SD_FAILURE) {
102         return;
103     }
104 
105     maxCoords = (*env)->GetArrayLength(env, coordsArray);
106     coords = (jfloat*)(*env)->GetPrimitiveArrayCritical(
107             env, coordsArray, NULL);
108     if (coords == NULL) {
109         SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
110         return;
111     }
112 
113     if (ret == SD_SLOWLOCK) {
114         GrPrim_RefineBounds(&rasInfo.bounds, transX, transY,
115                      coords, maxCoords);
116         ok = (rasInfo.bounds.x2 > rasInfo.bounds.x1 &&
117               rasInfo.bounds.y2 > rasInfo.bounds.y1);
118     }
119 
120     if (ok) {
121         sdOps->GetRasInfo(env, sdOps, &rasInfo);
122         if (rasInfo.rasBase) {
123             if (rasInfo.bounds.x2 > rasInfo.bounds.x1 &&
124                 rasInfo.bounds.y2 > rasInfo.bounds.y1)
125             {
126                 DrawHandlerData dHData;
127                 DrawHandler drawHandler = {
128                     NULL,
129                     NULL,
130                     &drawScanline,
131                     0, 0, 0, 0,
132                     0, 0, 0, 0,
133                     NULL
134                 };
135 
136                 jbyte *types = (jbyte*)(*env)->GetPrimitiveArrayCritical(
137                     env, typesArray, NULL);
138 
139                 /* Initialization of the following fields in the declaration of
140                  * the dHData and drawHandler above causes warnings on sun
141                  * studio compiler with
142                  * -xc99=%none option applied (this option means compliance
143                  *  with C90 standard instead of C99)
144                  */
145                 dHData.pRasInfo = &rasInfo;
146                 dHData.pixel = pixel;
147                 dHData.pPrim = pPrim;
148                 dHData.pCompInfo = &compInfo;
149 
150                 drawHandler.xMin = rasInfo.bounds.x1;
151                 drawHandler.yMin = rasInfo.bounds.y1;
152                 drawHandler.xMax = rasInfo.bounds.x2;
153                 drawHandler.yMax = rasInfo.bounds.y2;
154                 drawHandler.pData = &dHData;
155 
156                 if (types != NULL) {
157                     if (!doFillPath(&drawHandler,
158                                     transX, transY, coords,
159                                     maxCoords, types, numTypes,
160                                     (stroke == sunHints_INTVAL_STROKE_PURE)?
161                                             PH_STROKE_PURE : PH_STROKE_DEFAULT,
162                                     fillRule))
163                     {
164                         throwExc = JNI_TRUE;
165                     }
166 
167                     (*env)->ReleasePrimitiveArrayCritical(env, typesArray, types,
168                                                       JNI_ABORT);
169                 }
170             }
171         }
172         SurfaceData_InvokeRelease(env, sdOps, &rasInfo);
173     }
174     (*env)->ReleasePrimitiveArrayCritical(env, coordsArray, coords,
175                                           JNI_ABORT);
176 
177     if (throwExc) {
178         JNU_ThrowArrayIndexOutOfBoundsException(env,
179                                                 "coords array");
180     }
181 
182     SurfaceData_InvokeUnlock(env, sdOps, &rasInfo);
183 }
184