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;
217 jmethodID addExtensionID;
218 jmethodID addMimeTypeID;
221 formatClass = (*env)->FindClass
222 (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec");
224 g_assert(formatClass != NULL);
226 addExtensionID = (*env)->GetMethodID (env, formatClass,
228 "(Ljava/lang/String;)V");
230 addMimeTypeID = (*env)->GetMethodID (env, formatClass,
232 "(Ljava/lang/String;)V");
234 formats = gdk_pixbuf_get_formats ();
236 for (f = formats; f; f = f->next)
238 format = (GdkPixbufFormat *) f->data;
239 name = gdk_pixbuf_format_get_name(format);
241 string = (*env)->NewStringUTF(env, name);
242 g_assert(string != NULL);
244 jformat = (*env)->CallStaticObjectMethod
245 (env, clazz, registerFormatID, string,
246 (jboolean) gdk_pixbuf_format_is_writable(format));
247 (*env)->DeleteLocalRef(env, string);
250 g_assert(jformat != NULL);
252 ch = gdk_pixbuf_format_get_extensions(format);
256 string = (*env)->NewStringUTF(env, *ch);
257 g_assert(string != NULL);
258 (*env)->CallVoidMethod (env, jformat, addExtensionID, string);
259 (*env)->DeleteLocalRef(env, string);
263 g_strfreev(ch - count);
265 ch = gdk_pixbuf_format_get_mime_types(format);
269 string = (*env)->NewStringUTF(env, *ch);
270 g_assert(string != NULL);
271 (*env)->CallVoidMethod (env, jformat, addMimeTypeID, string);
272 (*env)->DeleteLocalRef(env, string);
276 g_strfreev(ch - count);
277 (*env)->DeleteLocalRef(env, jformat);
280 g_slist_free(formats);
284 JNIEXPORT void JNICALL
285 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState
286 (JNIEnv *env, jclass clazz)
290 (*env)->GetJavaVM(env, &vm);
292 areaPreparedID = (*env)->GetMethodID (env, clazz,
296 areaUpdatedID = (*env)->GetMethodID (env, clazz,
300 registerFormatID = (*env)->GetStaticMethodID
303 "(Ljava/lang/String;Z)"
304 "Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;");
306 writerClass = (*env)->FindClass
307 (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$GdkPixbufWriter");
308 dataOutputWriteID = (*env)->GetMethodID (env, writerClass,
311 query_formats (env, clazz);
313 NSA_PB_INIT (env, clazz);
317 JNIEXPORT void JNICALL
318 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish
319 (JNIEnv *env, jobject obj, jboolean needs_close)
321 GdkPixbufLoader *loader = NULL;
323 loader = (GdkPixbufLoader *)NSA_DEL_PB_PTR (env, obj);
328 gdk_pixbuf_loader_close (loader, NULL);
329 g_object_unref (loader);
332 JNIEXPORT void JNICALL
333 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpDone
334 (JNIEnv *env, jobject obj)
337 GdkPixbufLoader *loader = NULL;
339 loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj);
340 g_assert (loader != NULL);
342 gdk_pixbuf_loader_close (loader, &err);
346 JCL_ThrowException (env, "java/io/IOException", err->message);
351 struct stream_save_request
358 save_to_stream(const gchar *buf,
360 GError **error __attribute__((unused)),
363 struct stream_save_request *ssr = (struct stream_save_request *)data;
368 jbuf = (*(ssr->env))->NewByteArray ((ssr->env), count);
369 cbuf = (*(ssr->env))->GetByteArrayElements ((ssr->env), jbuf, NULL);
370 memcpy (cbuf, buf, count);
371 (*(ssr->env))->ReleaseByteArrayElements ((ssr->env), jbuf, cbuf, 0);
372 (*(ssr->env))->CallVoidMethod ((ssr->env), *(ssr->writer),
373 dataOutputWriteID, jbuf);
374 (*(ssr->env))->DeleteLocalRef((ssr->env), jbuf);
380 JNIEXPORT void JNICALL
381 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage
382 (JNIEnv *env, jclass clazz __attribute__((unused)),
383 jintArray jarr, jstring jenctype, jint width, jint height,
384 jboolean hasAlpha, jobject writer)
388 guchar a, r, g, b, *pix, *p;
392 struct stream_save_request ssr;
394 ssr.writer = &writer;
397 ints = (*env)->GetIntArrayElements (env, jarr, NULL);
398 pix = g_malloc(width * height * (hasAlpha ? 4 : 3));
400 enctype = (*env)->GetStringUTFChars (env, jenctype, NULL);
401 g_assert(enctype != NULL);
403 g_assert (pix != NULL);
404 g_assert (ints != NULL);
407 for (i = 0; i < width*height; ++i)
410 * Java encodes pixels as integers in a predictable arithmetic order:
411 * 0xAARRGGBB. Since these are jints, JNI has already byte-swapped
412 * them for us if necessary, so they're in "our" endianness, whatever
413 * that is. It uses 4 bytes per pixel whether or not there's an alpha
417 a = 0xff & (ints[i] >> 24);
418 r = 0xff & (ints[i] >> 16);
419 g = 0xff & (ints[i] >> 8);
423 * GDK-pixbuf has a very different storage model:
425 * - A different alpha order (alpha after colors).
426 * - A different packing model (no alpha -> 3-bytes-per-pixel).
427 * - A different "RGB" order (host memory order, not endian-neutral).
437 pixbuf = gdk_pixbuf_new_from_data (pix,
441 width * (hasAlpha ? 4 : 3), /* rowstride */
443 g_assert (pixbuf != NULL);
445 g_assert(gdk_pixbuf_save_to_callback (pixbuf,
451 g_object_unref (pixbuf);
455 (*env)->ReleaseStringUTFChars (env, jenctype, enctype);
456 (*env)->ReleaseIntArrayElements (env, jarr, ints, 0);
460 JNIEXPORT void JNICALL
461 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes
462 (JNIEnv *env, jobject obj, jbyteArray jarr, jint len)
464 GdkPixbufLoader *loader = NULL;
469 g_assert (jarr != NULL);
471 bytes = (*env)->GetByteArrayElements (env, jarr, NULL);
472 g_assert (bytes != NULL);
473 loader = (GdkPixbufLoader *)NSA_GET_PB_PTR (env, obj);
474 g_assert (loader != NULL);
476 gdk_pixbuf_loader_write (loader, (const guchar *) bytes, len, &err);
478 (*env)->ReleaseByteArrayElements (env, jarr, bytes, 0);
482 JCL_ThrowException (env, "java/io/IOException", err->message);