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 "gnu_java_awt_peer_gtk_GdkPixbufDecoder.h"
50 /* Union used for type punning. */
59 static jmethodID areaPreparedID;
60 static jmethodID areaUpdatedID;
61 static jmethodID dataOutputWriteID;
62 static jmethodID registerFormatID;
65 area_prepared_cb (GdkPixbufLoader *loader,
72 GdkPixbuf *pixbuf = NULL;
74 pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
75 g_assert (pixbuf != NULL);
77 width = gdk_pixbuf_get_width (pixbuf);
78 height = gdk_pixbuf_get_height (pixbuf);
80 g_assert (decoder != NULL);
83 (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
85 (*env)->CallVoidMethod (env,
92 area_updated_cb (GdkPixbufLoader *loader,
94 gint width, gint height,
99 jint stride_bytes, stride_pixels, n_channels, n_pixels;
104 GdkPixbuf *pixbuf_no_alpha = NULL;
105 GdkPixbuf *pixbuf = NULL;
107 #ifndef WORDS_BIGENDIAN
111 pixbuf_no_alpha = gdk_pixbuf_loader_get_pixbuf (loader);
112 if (pixbuf_no_alpha == NULL)
115 pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0);
116 g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
118 stride_bytes = gdk_pixbuf_get_rowstride (pixbuf);
119 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
120 stride_pixels = stride_bytes / n_channels;
121 n_pixels = height * stride_pixels;
122 gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
125 (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
127 jpixels = (*env)->NewIntArray (env, n_pixels);
129 java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL);
132 gdk_pixels + (y * stride_bytes),
133 (height * stride_bytes));
135 #ifndef WORDS_BIGENDIAN
136 /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */
137 for (i = 0; i < n_pixels; ++i)
139 java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]);
143 g_object_unref (pixbuf);
145 (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0);
147 (*env)->CallVoidMethod (env,
151 (jint) width, (jint) height,
155 (*env)->DeleteLocalRef(env, jpixels);
159 closed_cb (GdkPixbufLoader *loader __attribute__((unused)), jobject *decoder)
164 (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
166 (*env)->DeleteGlobalRef (env, *decoder);
172 JNIEXPORT void JNICALL
173 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState
174 (JNIEnv *env, jobject obj)
176 GdkPixbufLoader *loader = NULL;
177 jobject *decoder = NULL;
179 decoder = (jobject *) g_malloc (sizeof (jobject));
180 g_assert (decoder != NULL);
181 *decoder = (*env)->NewGlobalRef (env, obj);
183 loader = gdk_pixbuf_loader_new ();
184 g_assert (loader != NULL);
185 g_signal_connect (loader, "area-prepared", G_CALLBACK (area_prepared_cb), decoder);
186 g_signal_connect (loader, "area-updated", G_CALLBACK (area_updated_cb), decoder);
187 g_signal_connect (loader, "closed", G_CALLBACK (closed_cb), decoder);
189 gtkpeer_set_pixbuf_loader (env, obj, loader);
193 query_formats (JNIEnv *env, jclass clazz)
197 GdkPixbufFormat *format;
202 jmethodID addExtensionID;
203 jmethodID addMimeTypeID;
206 formatClass = (*env)->FindClass
207 (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec");
209 g_assert(formatClass != NULL);
211 addExtensionID = (*env)->GetMethodID (env, formatClass,
213 "(Ljava/lang/String;)V");
215 addMimeTypeID = (*env)->GetMethodID (env, formatClass,
217 "(Ljava/lang/String;)V");
219 formats = gdk_pixbuf_get_formats ();
221 for (f = formats; f; f = f->next)
223 format = (GdkPixbufFormat *) f->data;
224 name = gdk_pixbuf_format_get_name(format);
226 string = (*env)->NewStringUTF(env, name);
227 g_assert(string != NULL);
229 jformat = (*env)->CallStaticObjectMethod
230 (env, clazz, registerFormatID, string,
231 (jboolean) gdk_pixbuf_format_is_writable(format));
232 (*env)->DeleteLocalRef(env, string);
235 g_assert(jformat != NULL);
237 ch = gdk_pixbuf_format_get_extensions(format);
241 string = (*env)->NewStringUTF(env, *ch);
242 g_assert(string != NULL);
243 (*env)->CallVoidMethod (env, jformat, addExtensionID, string);
244 (*env)->DeleteLocalRef(env, string);
248 g_strfreev(ch - count);
250 ch = gdk_pixbuf_format_get_mime_types(format);
254 string = (*env)->NewStringUTF(env, *ch);
255 g_assert(string != NULL);
256 (*env)->CallVoidMethod (env, jformat, addMimeTypeID, string);
257 (*env)->DeleteLocalRef(env, string);
261 g_strfreev(ch - count);
262 (*env)->DeleteLocalRef(env, jformat);
265 g_slist_free(formats);
269 JNIEXPORT void JNICALL
270 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState
271 (JNIEnv *env, jclass clazz)
275 (*env)->GetJavaVM(env, &vm);
277 areaPreparedID = (*env)->GetMethodID (env, clazz,
281 areaUpdatedID = (*env)->GetMethodID (env, clazz,
285 registerFormatID = (*env)->GetStaticMethodID
288 "(Ljava/lang/String;Z)"
289 "Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;");
291 writerClass = (*env)->FindClass
292 (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$GdkPixbufWriter");
293 dataOutputWriteID = (*env)->GetMethodID (env, writerClass,
296 query_formats (env, clazz);
298 gtkpeer_init_pixbuf_IDs (env);
302 JNIEXPORT void JNICALL
303 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish
304 (JNIEnv *env, jobject obj, jboolean needs_close)
306 GdkPixbufLoader *loader = NULL;
308 loader = (GdkPixbufLoader *) gtkpeer_get_pixbuf_loader(env, obj);
313 gdk_pixbuf_loader_close (loader, NULL);
314 g_object_unref (loader);
317 JNIEXPORT void JNICALL
318 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpDone
319 (JNIEnv *env, jobject obj)
322 GdkPixbufLoader *loader = NULL;
324 loader = (GdkPixbufLoader *) gtkpeer_get_pixbuf_loader (env, obj);
325 g_assert (loader != NULL);
327 gdk_pixbuf_loader_close (loader, &err);
331 JCL_ThrowException (env, "java/io/IOException", err->message);
336 struct stream_save_request
343 save_to_stream(const gchar *buf,
345 GError **error __attribute__((unused)),
348 struct stream_save_request *ssr = (struct stream_save_request *)data;
353 jbuf = (*(ssr->env))->NewByteArray ((ssr->env), count);
354 cbuf = (*(ssr->env))->GetByteArrayElements ((ssr->env), jbuf, NULL);
355 memcpy (cbuf, buf, count);
356 (*(ssr->env))->ReleaseByteArrayElements ((ssr->env), jbuf, cbuf, 0);
357 (*(ssr->env))->CallVoidMethod ((ssr->env), *(ssr->writer),
358 dataOutputWriteID, jbuf);
359 (*(ssr->env))->DeleteLocalRef((ssr->env), jbuf);
365 JNIEXPORT void JNICALL
366 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage
367 (JNIEnv *env, jclass clazz __attribute__((unused)),
368 jintArray jarr, jstring jenctype, jint width, jint height,
369 jboolean hasAlpha, jobject writer)
373 guchar a, r, g, b, *pix, *p;
377 struct stream_save_request ssr;
379 ssr.writer = &writer;
382 ints = (*env)->GetIntArrayElements (env, jarr, NULL);
383 pix = g_malloc(width * height * (hasAlpha ? 4 : 3));
385 enctype = (*env)->GetStringUTFChars (env, jenctype, NULL);
386 g_assert(enctype != NULL);
388 g_assert (pix != NULL);
389 g_assert (ints != NULL);
392 for (i = 0; i < width*height; ++i)
395 * Java encodes pixels as integers in a predictable arithmetic order:
396 * 0xAARRGGBB. Since these are jints, JNI has already byte-swapped
397 * them for us if necessary, so they're in "our" endianness, whatever
398 * that is. It uses 4 bytes per pixel whether or not there's an alpha
402 a = 0xff & (ints[i] >> 24);
403 r = 0xff & (ints[i] >> 16);
404 g = 0xff & (ints[i] >> 8);
408 * GDK-pixbuf has a very different storage model:
410 * - A different alpha order (alpha after colors).
411 * - A different packing model (no alpha -> 3-bytes-per-pixel).
412 * - A different "RGB" order (host memory order, not endian-neutral).
422 pixbuf = gdk_pixbuf_new_from_data (pix,
426 width * (hasAlpha ? 4 : 3), /* rowstride */
428 g_assert (pixbuf != NULL);
430 g_assert(gdk_pixbuf_save_to_callback (pixbuf,
436 g_object_unref (pixbuf);
440 (*env)->ReleaseStringUTFChars (env, jenctype, enctype);
441 (*env)->ReleaseIntArrayElements (env, jarr, ints, 0);
445 JNIEXPORT void JNICALL
446 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes
447 (JNIEnv *env, jobject obj, jbyteArray jarr, jint len)
449 GdkPixbufLoader *loader = NULL;
454 g_assert (jarr != NULL);
456 bytes = (*env)->GetByteArrayElements (env, jarr, NULL);
457 g_assert (bytes != NULL);
458 loader = (GdkPixbufLoader *) gtkpeer_get_pixbuf_loader (env, obj);
459 g_assert (loader != NULL);
461 gdk_pixbuf_loader_write (loader, (const guchar *) bytes, len, &err);
463 (*env)->ReleaseByteArrayElements (env, jarr, bytes, 0);
467 JCL_ThrowException (env, "java/io/IOException", err->message);