2 Copyright (C) 1999, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
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
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. */
40 #include <gdk-pixbuf/gdk-pixbuf.h>
41 #include <gdk-pixbuf/gdk-pixbuf-loader.h>
45 #include "native_state.h"
46 #include "gnu_java_awt_peer_gtk_GdkPixbufDecoder.h"
51 static struct state_table *native_pixbufdecoder_state_table;
53 #define NSA_PB_INIT(env, clazz) \
54 native_pixbufdecoder_state_table = cp_gtk_init_state_table (env, clazz)
56 #define NSA_GET_PB_PTR(env, obj) \
57 cp_gtk_get_state (env, obj, native_pixbufdecoder_state_table)
59 #define NSA_SET_PB_PTR(env, obj, ptr) \
60 cp_gtk_set_state (env, obj, native_pixbufdecoder_state_table, (void *)ptr)
62 #define NSA_DEL_PB_PTR(env, obj) \
63 cp_gtk_remove_state_slot (env, obj, native_pixbufdecoder_state_table)
65 /* Union used for type punning. */
74 static jmethodID areaPreparedID;
75 static jmethodID areaUpdatedID;
76 static jmethodID dataOutputWriteID;
77 static jmethodID registerFormatID;
80 area_prepared_cb (GdkPixbufLoader *loader,
87 GdkPixbuf *pixbuf = NULL;
89 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
90 g_assert (pixbuf != NULL);
92 width = gdk_pixbuf_get_width (pixbuf);
93 height = gdk_pixbuf_get_height (pixbuf);
95 g_assert (decoder != NULL);
98 (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
100 (*env)->CallVoidMethod (env,
107 area_updated_cb (GdkPixbufLoader *loader,
109 gint width, gint height,
114 jint stride_bytes, stride_pixels, n_channels, n_pixels;
119 GdkPixbuf *pixbuf_no_alpha = NULL;
120 GdkPixbuf *pixbuf = NULL;
122 #ifndef WORDS_BIGENDIAN
126 pixbuf_no_alpha = gdk_pixbuf_loader_get_pixbuf (loader);
127 if (pixbuf_no_alpha == NULL)
130 pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0);
131 g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
133 stride_bytes = gdk_pixbuf_get_rowstride (pixbuf);
134 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
135 stride_pixels = stride_bytes / n_channels;
136 n_pixels = height * stride_pixels;
137 gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
140 (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
142 jpixels = (*env)->NewIntArray (env, n_pixels);
144 java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL);
147 gdk_pixels + (y * stride_bytes),
148 (height * stride_bytes));
150 #ifndef WORDS_BIGENDIAN
151 /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */
152 for (i = 0; i < n_pixels; ++i)
154 java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]);
158 g_object_unref (pixbuf);
160 (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0);
162 (*env)->CallVoidMethod (env,
166 (jint) width, (jint) height,
170 (*env)->DeleteLocalRef(env, jpixels);
174 closed_cb (GdkPixbufLoader *loader __attribute__((unused)), jobject *decoder)
179 (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
181 (*env)->DeleteGlobalRef (env, *decoder);
187 JNIEXPORT void JNICALL
188 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState
189 (JNIEnv *env, jobject obj)
191 GdkPixbufLoader *loader = NULL;
192 jobject *decoder = NULL;
194 decoder = (jobject *) g_malloc (sizeof (jobject));
195 g_assert (decoder != NULL);
196 *decoder = (*env)->NewGlobalRef (env, obj);
198 loader = gdk_pixbuf_loader_new ();
199 g_assert (loader != NULL);
200 g_signal_connect (loader, "area-prepared", G_CALLBACK (area_prepared_cb), decoder);
201 g_signal_connect (loader, "area-updated", G_CALLBACK (area_updated_cb), decoder);
202 g_signal_connect (loader, "closed", G_CALLBACK (closed_cb), decoder);
204 NSA_SET_PB_PTR (env, obj, loader);
208 query_formats (JNIEnv *env, jclass clazz)
212 GdkPixbufFormat *format;
216 jmethodID addExtensionID;
217 jmethodID addMimeTypeID;
220 formatClass = (*env)->FindClass
221 (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec");
223 g_assert(formatClass != NULL);
225 addExtensionID = (*env)->GetMethodID (env, formatClass,
227 "(Ljava/lang/String;)V");
229 addMimeTypeID = (*env)->GetMethodID (env, formatClass,
231 "(Ljava/lang/String;)V");
233 formats = gdk_pixbuf_get_formats ();
235 for (f = formats; f; f = f->next)
237 format = (GdkPixbufFormat *) f->data;
238 name = gdk_pixbuf_format_get_name(format);
240 string = (*env)->NewStringUTF(env, name);
241 g_assert(string != NULL);
243 jformat = (*env)->CallStaticObjectMethod
244 (env, clazz, registerFormatID, string,
245 (jboolean) gdk_pixbuf_format_is_writable(format));
246 (*env)->DeleteLocalRef(env, string);
248 g_assert(jformat != NULL);
250 ch = gdk_pixbuf_format_get_extensions(format);
253 string = (*env)->NewStringUTF(env, *ch);
254 g_assert(string != NULL);
255 (*env)->CallVoidMethod (env, jformat, addExtensionID, string);
256 (*env)->DeleteLocalRef(env, string);
260 ch = gdk_pixbuf_format_get_mime_types(format);
263 string = (*env)->NewStringUTF(env, *ch);
264 g_assert(string != NULL);
265 (*env)->CallVoidMethod (env, jformat, addMimeTypeID, string);
266 (*env)->DeleteLocalRef(env, string);
270 (*env)->DeleteLocalRef(env, jformat);
273 g_slist_free(formats);
277 JNIEXPORT void JNICALL
278 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState
279 (JNIEnv *env, jclass clazz)
283 (*env)->GetJavaVM(env, &vm);
285 areaPreparedID = (*env)->GetMethodID (env, clazz,
289 areaUpdatedID = (*env)->GetMethodID (env, clazz,
293 registerFormatID = (*env)->GetStaticMethodID
296 "(Ljava/lang/String;Z)"
297 "Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;");
299 writerClass = (*env)->FindClass
300 (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$GdkPixbufWriter");
301 dataOutputWriteID = (*env)->GetMethodID (env, writerClass,
304 query_formats (env, clazz);
306 NSA_PB_INIT (env, clazz);
310 JNIEXPORT void JNICALL
311 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish
312 (JNIEnv *env, jobject obj, jboolean needs_close)
314 GdkPixbufLoader *loader = NULL;
316 loader = (GdkPixbufLoader *)NSA_DEL_PB_PTR (env, obj);
321 gdk_pixbuf_loader_close (loader, NULL);
322 g_object_unref (loader);
325 JNIEXPORT void JNICALL
326 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpDone
327 (JNIEnv *env, jobject obj)
330 GdkPixbufLoader *loader = NULL;
332 loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj);
333 g_assert (loader != NULL);
335 gdk_pixbuf_loader_close (loader, &err);
339 JCL_ThrowException (env, "java/io/IOException", err->message);
344 struct stream_save_request
351 save_to_stream(const gchar *buf,
353 GError **error __attribute__((unused)),
356 struct stream_save_request *ssr = (struct stream_save_request *)data;
361 jbuf = (*(ssr->env))->NewByteArray ((ssr->env), count);
362 cbuf = (*(ssr->env))->GetByteArrayElements ((ssr->env), jbuf, NULL);
363 memcpy (cbuf, buf, count);
364 (*(ssr->env))->ReleaseByteArrayElements ((ssr->env), jbuf, cbuf, 0);
365 (*(ssr->env))->CallVoidMethod ((ssr->env), *(ssr->writer),
366 dataOutputWriteID, jbuf);
367 (*(ssr->env))->DeleteLocalRef((ssr->env), jbuf);
373 JNIEXPORT void JNICALL
374 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage
375 (JNIEnv *env, jclass clazz __attribute__((unused)),
376 jintArray jarr, jstring jenctype, jint width, jint height,
377 jboolean hasAlpha, jobject writer)
381 guchar a, r, g, b, *pix, *p;
385 struct stream_save_request ssr;
387 ssr.writer = &writer;
390 ints = (*env)->GetIntArrayElements (env, jarr, NULL);
391 pix = g_malloc(width * height * (hasAlpha ? 4 : 3));
393 enctype = (*env)->GetStringUTFChars (env, jenctype, NULL);
394 g_assert(enctype != NULL);
396 g_assert (pix != NULL);
397 g_assert (ints != NULL);
400 for (i = 0; i < width*height; ++i)
403 * Java encodes pixels as integers in a predictable arithmetic order:
404 * 0xAARRGGBB. Since these are jints, JNI has already byte-swapped
405 * them for us if necessary, so they're in "our" endianness, whatever
406 * that is. It uses 4 bytes per pixel whether or not there's an alpha
410 a = 0xff & (ints[i] >> 24);
411 r = 0xff & (ints[i] >> 16);
412 g = 0xff & (ints[i] >> 8);
416 * GDK-pixbuf has a very different storage model:
418 * - A different alpha order (alpha after colors).
419 * - A different packing model (no alpha -> 3-bytes-per-pixel).
420 * - A different "RGB" order (host memory order, not endian-neutral).
430 pixbuf = gdk_pixbuf_new_from_data (pix,
434 width * (hasAlpha ? 4 : 3), /* rowstride */
436 g_assert (pixbuf != NULL);
438 g_assert(gdk_pixbuf_save_to_callback (pixbuf,
444 g_object_unref (pixbuf);
448 (*env)->ReleaseStringUTFChars (env, jenctype, enctype);
449 (*env)->ReleaseIntArrayElements (env, jarr, ints, 0);
453 JNIEXPORT void JNICALL
454 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes
455 (JNIEnv *env, jobject obj, jbyteArray jarr, jint len)
457 GdkPixbufLoader *loader = NULL;
462 g_assert (jarr != NULL);
464 bytes = (*env)->GetByteArrayElements (env, jarr, NULL);
465 g_assert (bytes != NULL);
466 loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj);
467 g_assert (loader != NULL);
469 gdk_pixbuf_loader_write (loader, (const guchar *) bytes, len, &err);
471 (*env)->ReleaseByteArrayElements (env, jarr, bytes, 0);
475 JCL_ThrowException (env, "java/io/IOException", err->message);