2 Copyright (C) 1999, 2003, 2004 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., 59 Temple Place, Suite 330, 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>
44 #include "native_state.h"
45 #include "gnu_java_awt_peer_gtk_GdkPixbufDecoder.h"
50 struct state_table
*native_pixbufdecoder_state_table
;
52 /* Union used for type punning. */
61 static jmethodID areaPreparedID
;
62 static jmethodID areaUpdatedID
;
63 static jmethodID dataOutputWriteID
;
64 static jmethodID registerFormatID
;
67 area_prepared (GdkPixbufLoader
*loader
,
74 GdkPixbuf
*pixbuf
= gdk_pixbuf_loader_get_pixbuf (loader
);
78 width
= gdk_pixbuf_get_width (pixbuf
);
79 height
= gdk_pixbuf_get_height (pixbuf
);
83 g_assert (decoder
!= NULL
);
86 (*vm
)->GetEnv (vm
, e
.void_env
, JNI_VERSION_1_1
);
87 (*env
)->CallVoidMethod (env
,
96 area_updated (GdkPixbufLoader
*loader
,
98 gint width
, gint height
,
103 jint stride_bytes
, stride_pixels
, n_channels
, n_pixels
;
108 GdkPixbuf
*pixbuf_no_alpha
= NULL
;
109 GdkPixbuf
*pixbuf
= NULL
;
111 #ifndef WORDS_BIGENDIAN
115 pixbuf_no_alpha
= gdk_pixbuf_loader_get_pixbuf (loader
);
116 if (pixbuf_no_alpha
== NULL
)
119 pixbuf
= gdk_pixbuf_add_alpha(pixbuf_no_alpha
, FALSE
, 0, 0, 0);
120 g_assert (gdk_pixbuf_get_has_alpha (pixbuf
));
122 stride_bytes
= gdk_pixbuf_get_rowstride (pixbuf
);
123 n_channels
= gdk_pixbuf_get_n_channels (pixbuf
);
124 stride_pixels
= stride_bytes
/ n_channels
;
125 n_pixels
= height
* stride_pixels
;
126 gdk_pixels
= gdk_pixbuf_get_pixels (pixbuf
);
129 (*vm
)->GetEnv (vm
, e
.void_env
, JNI_VERSION_1_1
);
130 jpixels
= (*env
)->NewIntArray (env
, n_pixels
);
131 java_pixels
= (*env
)->GetIntArrayElements (env
, jpixels
, NULL
);
134 gdk_pixels
+ (y
* stride_bytes
),
135 (height
* stride_bytes
));
137 #ifndef WORDS_BIGENDIAN
138 /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */
139 for (i
= 0; i
< n_pixels
; ++i
)
141 java_pixels
[i
] = SWAPU32 ((unsigned)java_pixels
[i
]);
145 g_object_unref (pixbuf
);
147 gdk_threads_leave ();
149 (*env
)->ReleaseIntArrayElements (env
, jpixels
, java_pixels
, 0);
150 (*env
)->CallVoidMethod (env
,
154 (jint
) width
, (jint
) height
,
157 gdk_threads_enter ();
161 closed (GdkPixbufLoader
*loader
__attribute__((unused
)), jobject
*decoder
)
166 (*vm
)->GetEnv (vm
, e
.void_env
, JNI_VERSION_1_1
);
168 gdk_threads_leave ();
169 (*env
)->DeleteGlobalRef (env
, *decoder
);
171 gdk_threads_enter ();
176 JNIEXPORT
void JNICALL
177 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState
178 (JNIEnv
*env
, jobject obj
)
180 GdkPixbufLoader
*loader
= NULL
;
181 jobject
*decoder
= NULL
;
183 decoder
= (jobject
*) malloc (sizeof (jobject
));
184 g_assert (decoder
!= NULL
);
185 *decoder
= (*env
)->NewGlobalRef (env
, obj
);
187 gdk_threads_enter ();
188 loader
= gdk_pixbuf_loader_new ();
189 g_assert (loader
!= NULL
);
190 g_signal_connect (loader
, "area-prepared", G_CALLBACK (area_prepared
), decoder
);
191 g_signal_connect (loader
, "area-updated", G_CALLBACK (area_updated
), decoder
);
192 g_signal_connect (loader
, "closed", G_CALLBACK (closed
), decoder
);
193 gdk_threads_leave ();
195 NSA_SET_PB_PTR (env
, obj
, loader
);
199 query_formats (JNIEnv
*env
, jclass clazz
)
203 GdkPixbufFormat
*format
;
207 jmethodID addExtensionID
;
208 jmethodID addMimeTypeID
;
210 formatClass
= (*env
)->FindClass
211 (env
, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec");
213 g_assert(formatClass
!= NULL
);
215 addExtensionID
= (*env
)->GetMethodID (env
, formatClass
,
217 "(Ljava/lang/String;)V");
219 addMimeTypeID
= (*env
)->GetMethodID (env
, formatClass
,
221 "(Ljava/lang/String;)V");
223 formats
= gdk_pixbuf_get_formats ();
225 for (f
= formats
; f
; f
= f
->next
)
227 format
= (GdkPixbufFormat
*) f
->data
;
228 name
= gdk_pixbuf_format_get_name(format
);
230 jformat
= (*env
)->CallStaticObjectMethod
231 (env
, clazz
, registerFormatID
,
232 (*env
)->NewStringUTF(env
, name
),
233 (jboolean
) gdk_pixbuf_format_is_writable(format
));
235 g_assert(jformat
!= NULL
);
237 ch
= gdk_pixbuf_format_get_extensions(format
);
240 (*env
)->CallVoidMethod (env
, jformat
, addExtensionID
,
241 (*env
)->NewStringUTF(env
, *ch
));
245 ch
= gdk_pixbuf_format_get_mime_types(format
);
248 (*env
)->CallVoidMethod (env
, jformat
, addMimeTypeID
,
249 (*env
)->NewStringUTF(env
, *ch
));
254 g_slist_free(formats
);
258 JNIEXPORT
void JNICALL
259 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState
260 (JNIEnv
*env
, jclass clazz
)
262 jclass dataOutputClass
;
264 (*env
)->GetJavaVM(env
, &vm
);
266 areaPreparedID
= (*env
)->GetMethodID (env
, clazz
,
270 areaUpdatedID
= (*env
)->GetMethodID (env
, clazz
,
274 registerFormatID
= (*env
)->GetStaticMethodID
277 "(Ljava/lang/String;Z)"
278 "Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;");
281 dataOutputClass
= (*env
)->FindClass(env
, "java/io/DataOutput");
282 dataOutputWriteID
= (*env
)->GetMethodID (env
, dataOutputClass
,
285 query_formats (env
, clazz
);
287 NSA_PB_INIT (env
, clazz
);
291 JNIEXPORT
void JNICALL
292 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish
293 (JNIEnv
*env
, jobject obj
)
295 GdkPixbufLoader
*loader
= NULL
;
297 loader
= (GdkPixbufLoader
*)NSA_DEL_PB_PTR (env
, obj
);
301 gdk_threads_enter ();
302 gdk_pixbuf_loader_close (loader
, NULL
);
303 g_object_unref (loader
);
304 gdk_threads_leave ();
307 struct stream_save_request
314 save_to_stream(const gchar
*buf
,
316 GError
**error
__attribute__((unused
)),
319 struct stream_save_request
*ssr
= (struct stream_save_request
*)data
;
324 gdk_threads_leave ();
325 jbuf
= (*(ssr
->env
))->NewByteArray ((ssr
->env
), count
);
326 cbuf
= (*(ssr
->env
))->GetByteArrayElements ((ssr
->env
), jbuf
, NULL
);
327 memcpy (cbuf
, buf
, count
);
328 (*(ssr
->env
))->ReleaseByteArrayElements ((ssr
->env
), jbuf
, cbuf
, 0);
329 (*(ssr
->env
))->CallVoidMethod ((ssr
->env
), *(ssr
->stream
),
330 dataOutputWriteID
, jbuf
);
331 gdk_threads_enter ();
336 JNIEXPORT
void JNICALL
337 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage
338 (JNIEnv
*env
, jclass clazz
__attribute__((unused
)),
339 jintArray jarr
, jstring jenctype
, jint width
, jint height
,
340 jboolean hasAlpha
, jobject stream
)
344 guchar a
, r
, g
, b
, *pix
, *p
;
349 struct stream_save_request ssr
;
350 ssr
.stream
= &stream
;
353 ints
= (*env
)->GetIntArrayElements (env
, jarr
, NULL
);
354 pix
= g_malloc(width
* height
* (hasAlpha
? 4 : 3));
356 enctype
= (*env
)->GetStringUTFChars (env
, jenctype
, NULL
);
357 g_assert(enctype
!= NULL
);
359 g_assert (pix
!= NULL
);
360 g_assert (ints
!= NULL
);
363 for (i
= 0; i
< width
*height
; ++i
)
366 * Java encodes pixels as integers in a predictable arithmetic order:
367 * 0xAARRGGBB. Since these are jints, JNI has already byte-swapped
368 * them for us if necessary, so they're in "our" endianness, whatever
369 * that is. It uses 4 bytes per pixel whether or not there's an alpha
373 a
= 0xff & (ints
[i
] >> 24);
374 r
= 0xff & (ints
[i
] >> 16);
375 g
= 0xff & (ints
[i
] >> 8);
379 * GDK-pixbuf has a very different storage model:
381 * - A different alpha order (alpha after colors).
382 * - A different packing model (no alpha -> 3-bytes-per-pixel).
383 * - A different "RGB" order (host memory order, not endian-neutral).
393 gdk_threads_enter ();
394 pixbuf
= gdk_pixbuf_new_from_data (pix
,
398 width
* (hasAlpha
? 4 : 3), /* rowstride */
400 g_assert (pixbuf
!= NULL
);
402 g_assert(gdk_pixbuf_save_to_callback (pixbuf
,
408 g_object_unref (pixbuf
);
410 gdk_threads_leave ();
413 (*env
)->ReleaseStringUTFChars (env
, jenctype
, enctype
);
414 (*env
)->ReleaseIntArrayElements (env
, jarr
, ints
, 0);
417 JNIEXPORT
void JNICALL
418 Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes
419 (JNIEnv
*env
, jobject obj
, jbyteArray jarr
, jint len
)
421 GdkPixbufLoader
*loader
= NULL
;
427 bytes
= (*env
)->GetByteArrayElements (env
, jarr
, NULL
);
428 g_assert (bytes
!= NULL
);
429 loader
= (GdkPixbufLoader
*)NSA_GET_PB_PTR (env
, obj
);
430 g_assert (loader
!= NULL
);
432 gdk_threads_enter ();
433 gdk_pixbuf_loader_write (loader
, (const guchar
*) bytes
, len
, NULL
);
434 gdk_threads_leave ();
436 (*env
)->ReleaseByteArrayElements (env
, jarr
, bytes
, 0);