1/*
2 * Copyright (c) 1999, 2018, 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 "SurfaceData.h"
27
28#include "jni_util.h"
29#include "Disposer.h"
30
31#include "stdlib.h"
32#include "string.h"
33
34/**
35 * This include file contains information on how to use a SurfaceData
36 * object from native code.
37 */
38
39static jclass pInvalidPipeClass;
40static jclass pNullSurfaceDataClass;
41static jfieldID pDataID;
42static jfieldID allGrayID;
43
44jfieldID validID;
45GeneralDisposeFunc SurfaceData_DisposeOps;
46
47#define InitClass(var, env, name) \
48do { \
49 var = (*env)->FindClass(env, name); \
50 if (var == NULL) { \
51 return; \
52 } \
53} while (0)
54
55#define InitField(var, env, jcl, name, type) \
56do { \
57 var = (*env)->GetFieldID(env, jcl, name, type); \
58 if (var == NULL) { \
59 return; \
60 } \
61} while (0)
62
63#define InitGlobalClassRef(var, env, name) \
64do { \
65 jobject jtmp; \
66 InitClass(jtmp, env, name); \
67 var = (*env)->NewGlobalRef(env, jtmp); \
68 if (var == NULL) { \
69 return; \
70 } \
71} while (0)
72
73/*
74 * Class: sun_java2d_SurfaceData
75 * Method: initIDs
76 * Signature: ()V
77 */
78JNIEXPORT void JNICALL
79Java_sun_java2d_SurfaceData_initIDs(JNIEnv *env, jclass sd)
80{
81 jclass pICMClass;
82
83 InitGlobalClassRef(pInvalidPipeClass, env,
84 "sun/java2d/InvalidPipeException");
85
86 InitGlobalClassRef(pNullSurfaceDataClass, env,
87 "sun/java2d/NullSurfaceData");
88
89 InitField(pDataID, env, sd, "pData", "J");
90 InitField(validID, env, sd, "valid", "Z");
91
92 InitClass(pICMClass, env, "java/awt/image/IndexColorModel");
93 InitField(allGrayID, env, pICMClass, "allgrayopaque", "Z");
94}
95
96/*
97 * Class: sun_java2d_SurfaceData
98 * Method: isOpaqueGray
99 * Signature: ()Z
100 */
101JNIEXPORT jboolean JNICALL
102Java_sun_java2d_SurfaceData_isOpaqueGray(JNIEnv *env, jclass sdClass,
103 jobject icm)
104{
105 if (icm == NULL) {
106 return JNI_FALSE;
107 }
108 return (*env)->GetBooleanField(env, icm, allGrayID);
109}
110
111static SurfaceDataOps *
112GetSDOps(JNIEnv *env, jobject sData, jboolean callSetup)
113{
114 SurfaceDataOps *ops;
115 if (JNU_IsNull(env, sData)) {
116 JNU_ThrowNullPointerException(env, "surfaceData");
117 return NULL;
118 }
119 ops = (SurfaceDataOps *)JNU_GetLongFieldAsPtr(env, sData, pDataID);
120 if (ops == NULL) {
121 if (!(*env)->ExceptionOccurred(env) &&
122 !(*env)->IsInstanceOf(env, sData, pNullSurfaceDataClass))
123 {
124 if (!(*env)->GetBooleanField(env, sData, validID)) {
125 SurfaceData_ThrowInvalidPipeException(env, "invalid data");
126 } else {
127 JNU_ThrowNullPointerException(env, "native ops missing");
128 }
129 }
130 } else if (callSetup) {
131 SurfaceData_InvokeSetup(env, ops);
132 }
133 return ops;
134}
135
136JNIEXPORT SurfaceDataOps * JNICALL
137SurfaceData_GetOps(JNIEnv *env, jobject sData)
138{
139 return GetSDOps(env, sData, JNI_TRUE);
140}
141
142JNIEXPORT SurfaceDataOps * JNICALL
143SurfaceData_GetOpsNoSetup(JNIEnv *env, jobject sData)
144{
145 return GetSDOps(env, sData, JNI_FALSE);
146}
147
148JNIEXPORT void JNICALL
149SurfaceData_SetOps(JNIEnv *env, jobject sData, SurfaceDataOps *ops)
150{
151 if (JNU_GetLongFieldAsPtr(env, sData, pDataID) == NULL) {
152 JNU_SetLongFieldFromPtr(env, sData, pDataID, ops);
153 /* Register the data for disposal */
154 Disposer_AddRecord(env, sData,
155 SurfaceData_DisposeOps,
156 ptr_to_jlong(ops));
157 } else {
158 JNU_ThrowInternalError(env, "Attempting to set SurfaceData ops twice");
159 }
160}
161
162JNIEXPORT void JNICALL
163SurfaceData_ThrowInvalidPipeException(JNIEnv *env, const char *msg)
164{
165 (*env)->ThrowNew(env, pInvalidPipeClass, msg);
166}
167
168#define GETMIN(v1, v2) (((v1) > (t=(v2))) && ((v1) = t))
169#define GETMAX(v1, v2) (((v1) < (t=(v2))) && ((v1) = t))
170
171JNIEXPORT void JNICALL
172SurfaceData_IntersectBounds(SurfaceDataBounds *dst, SurfaceDataBounds *src)
173{
174 int t;
175 GETMAX(dst->x1, src->x1);
176 GETMAX(dst->y1, src->y1);
177 GETMIN(dst->x2, src->x2);
178 GETMIN(dst->y2, src->y2);
179}
180
181JNIEXPORT void JNICALL
182SurfaceData_IntersectBoundsXYXY(SurfaceDataBounds *bounds,
183 jint x1, jint y1, jint x2, jint y2)
184{
185 int t;
186 GETMAX(bounds->x1, x1);
187 GETMAX(bounds->y1, y1);
188 GETMIN(bounds->x2, x2);
189 GETMIN(bounds->y2, y2);
190}
191
192JNIEXPORT void JNICALL
193SurfaceData_IntersectBoundsXYWH(SurfaceDataBounds *bounds,
194 jint x, jint y, jint w, jint h)
195{
196 w = (w <= 0) ? x : x+w;
197 if (w < x) {
198 w = 0x7fffffff;
199 }
200 if (bounds->x1 < x) {
201 bounds->x1 = x;
202 }
203 if (bounds->x2 > w) {
204 bounds->x2 = w;
205 }
206 h = (h <= 0) ? y : y+h;
207 if (h < y) {
208 h = 0x7fffffff;
209 }
210 if (bounds->y1 < y) {
211 bounds->y1 = y;
212 }
213 if (bounds->y2 > h) {
214 bounds->y2 = h;
215 }
216}
217
218JNIEXPORT void JNICALL
219SurfaceData_IntersectBlitBounds(SurfaceDataBounds *src,
220 SurfaceDataBounds *dst,
221 jint dx, jint dy)
222{
223 int t;
224 GETMAX(dst->x1, src->x1 + dx);
225 GETMAX(dst->y1, src->y1 + dy);
226 GETMIN(dst->x2, src->x2 + dx);
227 GETMIN(dst->y2, src->y2 + dy);
228 GETMAX(src->x1, dst->x1 - dx);
229 GETMAX(src->y1, dst->y1 - dy);
230 GETMIN(src->x2, dst->x2 - dx);
231 GETMIN(src->y2, dst->y2 - dy);
232}
233
234JNIEXPORT SurfaceDataOps * JNICALL
235SurfaceData_InitOps(JNIEnv *env, jobject sData, int opsSize)
236{
237 SurfaceDataOps *ops = malloc(opsSize);
238 SurfaceData_SetOps(env, sData, ops);
239 if (ops != NULL) {
240 memset(ops, 0, opsSize);
241 if (!(*env)->ExceptionCheck(env)) {
242 ops->sdObject = (*env)->NewWeakGlobalRef(env, sData);
243 }
244 }
245 return ops;
246}
247
248void SurfaceData_DisposeOps(JNIEnv *env, jlong ops)
249{
250 if (ops != 0) {
251 SurfaceDataOps *sdops = (SurfaceDataOps*)jlong_to_ptr(ops);
252 /* Invoke the ops-specific disposal function */
253 SurfaceData_InvokeDispose(env, sdops);
254 (*env)->DeleteWeakGlobalRef(env, sdops->sdObject);
255 free(sdops);
256 }
257}
258