1 /* gnu_java_awt_peer_gtk_CairoSurface.c
2 Copyright (C) 2006 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 #include "jcl.h"
39 #include "gtkpeer.h"
40
41 #include "gnu_java_awt_peer_gtk_CairoSurface.h"
42 #include "cairographics2d.h"
43
44 /**
45 * Field names in CairoSurface.java
46 */
47 #define SURFACE "surfacePointer"
48 #define SHARED "sharedBuffer"
49
50 /* prototypes */
51 static void setNativeObject( JNIEnv *env, jobject obj, void *ptr, const char *pointer );
52
53 /**
54 * Creates a cairo surface, ARGB32, native ordering, premultiplied alpha.
55 */
56 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_create(JNIEnv * env,jobject obj,jint width,jint height,jint stride,jintArray buf)57 Java_gnu_java_awt_peer_gtk_CairoSurface_create
58 (JNIEnv *env, jobject obj, jint width, jint height, jint stride,
59 jintArray buf )
60 {
61 cairo_surface_t* surface;
62 jboolean isCopy;
63
64 /* Retrieve java-created data array */
65 void *data = (*env)->GetIntArrayElements (env, buf, &isCopy);
66
67 /* Set sharedBuffer variable */
68 jclass cls = (*env)->GetObjectClass (env, obj);
69 jfieldID field = (*env)->GetFieldID (env, cls, SHARED, "Z");
70 g_assert (field != 0);
71
72 if (isCopy == JNI_TRUE)
73 {
74 (*env)->SetBooleanField (env, obj, field, JNI_FALSE);
75 void* temp = g_malloc(stride * height * 4);
76 memcpy(temp, data, stride * height * 4);
77 (*env)->ReleaseIntArrayElements (env, buf, data, 0);
78 data = temp;
79 }
80 else
81 (*env)->SetBooleanField (env, obj, field, JNI_TRUE);
82
83 /* Create the cairo surface and set the java pointer */
84 surface = cairo_image_surface_create_for_data
85 (data, CAIRO_FORMAT_ARGB32, width, height, stride * 4);
86
87 setNativeObject(env, obj, surface, SURFACE);
88 }
89
90 /**
91 * Destroy the surface
92 */
93 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_destroy(JNIEnv * env,jobject obj,jlong surfacePointer,jintArray buf)94 Java_gnu_java_awt_peer_gtk_CairoSurface_destroy
95 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
96 jlong surfacePointer, jintArray buf)
97 {
98 cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
99 void *data = cairo_image_surface_get_data(surface);
100 if( surface != NULL )
101 {
102 /* Release or free the data buffer as appropriate */
103 jclass cls = (*env)->GetObjectClass (env, obj);
104 jfieldID field = (*env)->GetFieldID (env, cls, SHARED, "Z");
105 g_assert (field != 0);
106 jboolean sharedBuffer = (*env)->GetBooleanField (env, obj, field);
107
108 if (sharedBuffer == JNI_TRUE)
109 (*env)->ReleaseIntArrayElements (env, buf, data, 0);
110 else
111 g_free(data);
112
113 /* Destroy the cairo surface itself */
114 cairo_surface_destroy(surface);
115 }
116 }
117
118 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_nativeDrawSurface(JNIEnv * env,jobject obj,jlong surfacePointer,jlong context,jdoubleArray java_matrix,double alpha,jint interpolation)119 Java_gnu_java_awt_peer_gtk_CairoSurface_nativeDrawSurface
120 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
121 jlong surfacePointer, jlong context, jdoubleArray java_matrix, double alpha,
122 jint interpolation)
123 {
124 struct cairographics2d *gr = JLONG_TO_PTR(struct cairographics2d, context);
125 cairo_t *cr = gr->cr;
126 jdouble *native_matrix = NULL;
127 cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
128 g_assert(surface != NULL);
129 g_assert(cr != NULL);
130
131 native_matrix = (*env)->GetDoubleArrayElements (env, java_matrix, NULL);
132 g_assert (native_matrix != NULL);
133 g_assert ((*env)->GetArrayLength (env, java_matrix) == 6);
134
135 {
136 cairo_matrix_t mat;
137 cairo_pattern_t *p;
138 cairo_matrix_init_identity (&mat);
139 cairo_matrix_init (&mat,
140 native_matrix[0], native_matrix[1],
141 native_matrix[2], native_matrix[3],
142 native_matrix[4], native_matrix[5]);
143
144 p = cairo_pattern_create_for_surface (surface);
145 cairo_pattern_set_matrix (p, &mat);
146 switch ((enum java_awt_rendering_hints_filter) interpolation)
147 {
148 case java_awt_rendering_hints_VALUE_INTERPOLATION_NEAREST_NEIGHBOR:
149 cairo_pattern_set_filter (p, CAIRO_FILTER_NEAREST);
150 break;
151 case java_awt_rendering_hints_VALUE_INTERPOLATION_BILINEAR:
152 cairo_pattern_set_filter (p, CAIRO_FILTER_BILINEAR);
153 break;
154 case java_awt_rendering_hints_VALUE_INTERPOLATION_BICUBIC:
155 cairo_pattern_set_filter (p, CAIRO_FILTER_GAUSSIAN);
156 break;
157 case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_SPEED:
158 cairo_pattern_set_filter (p, CAIRO_FILTER_FAST);
159 break;
160 case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_DEFAULT:
161 cairo_pattern_set_filter (p, CAIRO_FILTER_NEAREST);
162 break;
163 case java_awt_rendering_hints_VALUE_ALPHA_INTERPOLATION_QUALITY:
164 cairo_pattern_set_filter (p, CAIRO_FILTER_BEST);
165 break;
166 }
167
168 cairo_set_source(cr, p);
169 if (alpha == 1.0)
170 cairo_paint(cr);
171 else
172 cairo_paint_with_alpha(cr, alpha);
173
174 cairo_pattern_destroy(p);
175 }
176
177 (*env)->ReleaseDoubleArrayElements (env, java_matrix, native_matrix, 0);
178 }
179
180 JNIEXPORT jlong JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_getFlippedBuffer(JNIEnv * env,jobject obj,jlong surfacePointer)181 Java_gnu_java_awt_peer_gtk_CairoSurface_getFlippedBuffer
182 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
183 jlong surfacePointer)
184 {
185 cairo_surface_t* surface;
186 jint *src;
187 jint *dst;
188 int i, t, width, height;
189 jclass cls;
190 jfieldID field;
191
192 /* Retrieve pointer to cairo data buffer */
193 surface = JLONG_TO_PTR(void, surfacePointer);
194 src = (jint*)cairo_image_surface_get_data(surface);
195
196 /* Retrieve dimensions of surface, from java fields */
197 cls = (*env)->GetObjectClass (env, obj);
198 field = (*env)->GetFieldID (env, cls, "width", "I");
199 g_assert (field != 0);
200 width = (*env)->GetIntField (env, obj, field);
201
202 field = (*env)->GetFieldID (env, cls, "height", "I");
203 g_assert (field != 0);
204 height = (*env)->GetIntField (env, obj, field);
205
206 /* Create destination array */
207 g_assert( src != NULL );
208 dst = g_malloc( width * height * sizeof( jint ) );
209
210 /* Copy data into destination array, reversing sample order of each pixel */
211 for(i = 0; i < (height * width); i++ )
212 {
213 t = (src[i] & 0x0000FF) << 16;
214 dst[i] = (src[i] & 0x00FF0000) >> 16;
215 dst[i] |= (src[i] & 0xFF00FF00);
216 dst[i] |= t;
217 }
218
219 return PTR_TO_JLONG(dst);
220 }
221
222 /**
223 * Create and return a cairo context for drawing to the surface.
224 */
225 JNIEXPORT jlong JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_nativeNewCairoContext(JNIEnv * env __attribute ((unused)),jobject obj __attribute ((unused)),jlong surfacePointer)226 Java_gnu_java_awt_peer_gtk_CairoSurface_nativeNewCairoContext
227 (JNIEnv *env __attribute((unused)), jobject obj __attribute((unused)),
228 jlong surfacePointer)
229 {
230 cairo_surface_t* surface = JLONG_TO_PTR(cairo_surface_t, surfacePointer);
231 cairo_t *ptr;
232 g_assert(surface != NULL);
233 ptr = cairo_create(surface);
234 g_assert(ptr != NULL);
235
236 return PTR_TO_JLONG(ptr);
237 }
238
239 /**
240 * copyArea.
241 */
242 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_copyAreaNative2(JNIEnv * env,jobject obj,jlong surfacePointer,jint x,jint y,jint w,jint h,jint dx,jint dy,jint stride)243 Java_gnu_java_awt_peer_gtk_CairoSurface_copyAreaNative2
244 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
245 jlong surfacePointer,
246 jint x, jint y, jint w, jint h, jint dx, jint dy, jint stride)
247 {
248 int row;
249 int srcOffset, dstOffset;
250 jint *temp;
251
252 /* Retrieve pointer to cairo data buffer */
253 cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
254 jint *pixeldata = (jint*)cairo_image_surface_get_data(surface);
255 g_assert( pixeldata != NULL );
256
257 /* Create temporary buffer and calculate offsets */
258 temp = g_malloc( h * w * 4 );
259 g_assert( temp != NULL );
260
261 srcOffset = x + (y * stride);
262 dstOffset = (x + dx) + ((y + dy) * stride);
263
264 /* Copy desired region into temporary buffer */
265 for( row = 0; row < h; row++ )
266 memcpy( temp + (w * row), pixeldata + srcOffset + (stride * row), w * 4 );
267
268 /* Copy out of buffer and to destination */
269 for( row = 0; row < h; row++ )
270 memcpy( pixeldata + dstOffset + (stride * row), temp + (w * row), w * 4 );
271
272 g_free( temp );
273 }
274
275 /*
276 * Synchronizes the java and native data buffers, copying any changes made in
277 * the java array into the native array.
278 * This method should only be called if (sharedBuffer == false).
279 */
280 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_syncJavaToNative(JNIEnv * env,jobject obj,jlong surfacePointer,jintArray buffer)281 Java_gnu_java_awt_peer_gtk_CairoSurface_syncJavaToNative
282 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
283 jlong surfacePointer, jintArray buffer)
284 {
285 /* Get size of java array */
286 int size = (*env)->GetArrayLength(env, buffer);
287
288 /* Get native data buffer */
289 cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
290 g_assert(surface != NULL);
291 void* nativeBuffer = cairo_image_surface_get_data(surface);
292
293 /* Sync buffers */
294 (*env)->GetIntArrayRegion(env, buffer, 0, size, nativeBuffer);
295 }
296
297 /*
298 * Synchronizes the java and native data buffers, copying any changes made in
299 * the native array into the java array.
300 * This method should only be called if (sharedBuffer == false).
301 */
302 JNIEXPORT void JNICALL
Java_gnu_java_awt_peer_gtk_CairoSurface_syncNativeToJava(JNIEnv * env,jobject obj,jlong surfacePointer,jintArray buffer)303 Java_gnu_java_awt_peer_gtk_CairoSurface_syncNativeToJava
304 (JNIEnv *env __attribute__((unused)), jobject obj __attribute__((unused)),
305 jlong surfacePointer, jintArray buffer)
306 {
307 /* Get size of java array */
308 int size = (*env)->GetArrayLength(env, buffer);
309
310 /* Get native data buffer */
311 cairo_surface_t* surface = JLONG_TO_PTR(void, surfacePointer);
312 g_assert(surface != NULL);
313 void* nativeBuffer = cairo_image_surface_get_data(surface);
314
315 /* Sync buffers */
316 (*env)->SetIntArrayRegion(env, buffer, 0, size, nativeBuffer);
317 }
318
319 /*
320 * Sets the native object field.
321 */
322 static void
setNativeObject(JNIEnv * env,jobject obj,void * ptr,const char * pointer)323 setNativeObject( JNIEnv *env, jobject obj, void *ptr, const char *pointer )
324 {
325 jclass cls;
326 jlong value;
327 jfieldID nofid;
328 cls = (*env)->GetObjectClass( env, obj );
329 value = PTR_TO_JLONG(ptr);
330 nofid = (*env)->GetFieldID( env, cls, pointer, "J" );
331 (*env)->SetLongField( env, obj, nofid, value );
332 (*env)->DeleteLocalRef( env, cls );
333 }
334