2 Copyright (C) 2005 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 "gnu_java_awt_peer_gtk_GtkImage.h"
41 #include <gdk-pixbuf/gdk-pixbuf.h>
43 /* The constant fields in java.awt.Image */
44 #define SCALE_DEFAULT 1
46 #define SCALE_SMOOTH 4
47 #define SCALE_REPLICATE 8
48 #define SCALE_AREA_AVERAGING 16
51 static GdkInterpType
mapHints(jint hints
);
52 static jboolean
offScreen (JNIEnv
* env
, jobject obj
);
53 static void *getData (JNIEnv
* env
, jobject obj
);
54 static void createRawData (JNIEnv
* env
, jobject obj
, void *ptr
);
55 static void setWidthHeight (JNIEnv
* env
, jobject obj
, int width
, int height
);
58 * Loads a pixmap from a file.
60 JNIEXPORT jboolean JNICALL
61 Java_gnu_java_awt_peer_gtk_GtkImage_loadPixbuf
62 (JNIEnv
*env
, jobject obj
, jstring name
)
70 /* Don't use the JCL convert function because it throws an exception
72 filename
= (*env
)->GetStringUTFChars (env
, name
, 0);
80 pixbuf
= gdk_pixbuf_new_from_file (filename
, NULL
);
83 (*env
)->ReleaseStringUTFChars (env
, name
, filename
);
88 width
= gdk_pixbuf_get_width (pixbuf
);
89 height
= gdk_pixbuf_get_height (pixbuf
);
91 createRawData (env
, obj
, pixbuf
);
92 setWidthHeight(env
, obj
, width
, height
);
93 (*env
)->ReleaseStringUTFChars (env
, name
, filename
);
101 * Creates the image from an array of java bytes.
103 JNIEXPORT jboolean JNICALL
104 Java_gnu_java_awt_peer_gtk_GtkImage_loadImageFromData
105 (JNIEnv
*env
, jobject obj
, jbyteArray data
)
109 GdkPixbufLoader
* loader
;
114 gdk_threads_enter ();
116 src
= (*env
)->GetByteArrayElements (env
, data
, NULL
);
117 len
= (*env
)->GetArrayLength (env
, data
);
119 loader
= gdk_pixbuf_loader_new ();
121 gdk_pixbuf_loader_write (loader
, (guchar
*)src
, len
, NULL
);
122 gdk_pixbuf_loader_close (loader
, NULL
);
124 (*env
)->ReleaseByteArrayElements (env
, data
, src
, 0);
126 pixbuf
= gdk_pixbuf_loader_get_pixbuf (loader
);
130 createRawData (env
, obj
, NULL
);
132 gdk_threads_leave ();
137 width
= gdk_pixbuf_get_width (pixbuf
);
138 height
= gdk_pixbuf_get_height (pixbuf
);
140 createRawData (env
, obj
, pixbuf
);
141 setWidthHeight(env
, obj
, width
, height
);
143 gdk_threads_leave ();
148 JNIEXPORT
void JNICALL
149 Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf
150 (JNIEnv
*env
, jobject obj
)
153 GdkPixbuf
*pixbuf
= (GdkPixbuf
*) getData (env
, obj
);
154 gdk_threads_enter ();
155 width
= gdk_pixbuf_get_width (pixbuf
);
156 heigth
= gdk_pixbuf_get_height (pixbuf
);
157 gdk_threads_leave ();
158 setWidthHeight(env
, obj
, width
, heigth
);
162 * Returns a copy of the pixel data as a java array.
164 JNIEXPORT jintArray JNICALL
165 Java_gnu_java_awt_peer_gtk_GtkImage_getPixels(JNIEnv
*env
, jobject obj
)
168 int width
, height
, rowstride
;
170 jintArray result_array
;
171 jint
*result_array_iter
, *dst
;
174 gdk_threads_enter ();
176 pixbuf
= cp_gtk_image_get_pixbuf (env
, obj
);
177 width
= gdk_pixbuf_get_width (pixbuf
);
178 height
= gdk_pixbuf_get_height (pixbuf
);
179 rowstride
= gdk_pixbuf_get_rowstride (pixbuf
);
181 result_array
= (*env
)->NewIntArray (env
, (width
* height
));
183 dst
= result_array_iter
=
184 (*env
)->GetIntArrayElements (env
, result_array
, NULL
);
187 pixeldata
= gdk_pixbuf_get_pixels (pixbuf
);
189 g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
191 if (gdk_pixbuf_get_has_alpha (pixbuf
))
193 for(i
= 0 ; i
< height
; i
++)
195 memcpy(dst
, (void *)pixeldata
, width
* 4);
197 pixeldata
+= rowstride
;
200 for(i
= 0; i
< height
; i
++)
202 for(j
= 0; j
< width
; j
++)
203 dst
[j
] = 0xFF000000 |
204 (pixeldata
[j
*3 + 2] & 0xFF) << 16 |
205 (pixeldata
[j
*3 + 1] & 0xFF) << 8 |
206 (pixeldata
[j
*3] & 0xFF);
208 pixeldata
+= rowstride
;
212 if (offScreen (env
, obj
) == JNI_TRUE
)
213 gdk_pixbuf_unref (pixbuf
);
215 (*env
)->ReleaseIntArrayElements (env
, result_array
, result_array_iter
, 0);
217 gdk_threads_leave ();
223 * Returns a copy of the pixel data as a java array.
226 JNIEXPORT
void JNICALL
227 Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv
*env
, jobject obj
,
230 GdkPixbuf
*pixbuf
= (GdkPixbuf
*)getData (env
, obj
);
231 int width
, height
, rowstride
;
233 jint
*src_array_iter
, *src
;
236 gdk_threads_enter ();
238 width
= gdk_pixbuf_get_width (pixbuf
);
239 height
= gdk_pixbuf_get_height (pixbuf
);
240 rowstride
= gdk_pixbuf_get_rowstride (pixbuf
);
242 src
= src_array_iter
=
243 (*env
)->GetIntArrayElements (env
, pixels
, NULL
);
245 pixeldata
= gdk_pixbuf_get_pixels (pixbuf
);
246 for(i
= 0 ; i
< height
; i
++)
248 memcpy((void *)pixeldata
, (void *)src
, width
* 4);
250 pixeldata
+= rowstride
;
253 (*env
)->ReleaseIntArrayElements (env
, pixels
, src_array_iter
, 0);
255 gdk_threads_leave ();
259 * Allocates a Gtk Pixbuf or Pixmap.
261 JNIEXPORT
void JNICALL
262 Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap(JNIEnv
*env
, jobject obj
)
268 gdk_threads_enter ();
270 cls
= (*env
)->GetObjectClass (env
, obj
);
271 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
272 g_assert (field
!= 0);
273 width
= (*env
)->GetIntField (env
, obj
, field
);
275 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
276 g_assert (field
!= 0);
277 height
= (*env
)->GetIntField (env
, obj
, field
);
279 if (offScreen (env
, obj
) == JNI_FALSE
)
280 createRawData (env
, obj
, gdk_pixbuf_new (GDK_COLORSPACE_RGB
,
286 createRawData (env
, obj
, gdk_pixmap_new (NULL
, width
, height
,
287 gdk_rgb_get_visual ()->depth
));
289 gdk_threads_leave ();
293 * Frees the Gtk Pixmap.
295 JNIEXPORT
void JNICALL
296 Java_gnu_java_awt_peer_gtk_GtkImage_freePixmap(JNIEnv
*env
, jobject obj
)
298 gdk_threads_enter ();
299 if (offScreen (env
, obj
) == JNI_FALSE
)
300 gdk_pixbuf_unref ((GdkPixbuf
*)getData (env
, obj
));
302 g_object_unref ((GdkPixmap
*)getData (env
, obj
));
304 gdk_threads_leave ();
308 * Sets this pixmap to a scaled version of the source pixmap.
309 * width and height of the destination GtkImage must be set.
311 JNIEXPORT
void JNICALL
312 Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap(JNIEnv
*env
,
324 gdk_threads_enter ();
326 cls
= (*env
)->GetObjectClass (env
, destination
);
327 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
328 g_assert (field
!= 0);
329 width
= (*env
)->GetIntField (env
, destination
, field
);
331 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
332 g_assert (field
!= 0);
333 height
= (*env
)->GetIntField (env
, destination
, field
);
335 pixbuf
= cp_gtk_image_get_pixbuf (env
, source
);
337 dst
= gdk_pixbuf_scale_simple(pixbuf
,
341 if (offScreen (env
, source
) == JNI_TRUE
)
342 gdk_pixbuf_unref (pixbuf
);
344 createRawData (env
, destination
, (void *)dst
);
346 gdk_threads_leave ();
350 * Draws the pixbuf at x, y, scaled to width and height and
351 * optionally composited with a given background color.
353 JNIEXPORT
void JNICALL
354 Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaled
355 (JNIEnv
*env
, jobject obj
, jobject gc_obj
,
356 jint bg_red
, jint bg_green
, jint bg_blue
,
357 jint x
, jint y
, jint width
, jint height
, jboolean composite
)
363 gdk_threads_enter ();
365 if (width
<= 0 || height
<= 0)
367 gdk_threads_leave ();
371 bgColor
= ((bg_red
& 0xFF) << 16) |
372 ((bg_green
& 0xFF) << 8) | (bg_blue
& 0xFF);
374 g
= (struct graphics
*) NSA_GET_G_PTR (env
, gc_obj
);
376 if (!g
|| !GDK_IS_DRAWABLE (g
->drawable
))
378 gdk_threads_leave ();
382 if (offScreen (env
, obj
) == JNI_FALSE
)
384 GdkPixbuf
* pixbuf
= (GdkPixbuf
*)getData (env
, obj
);
386 /* Scale and composite the image */
387 if (composite
== JNI_TRUE
)
388 dst
= gdk_pixbuf_composite_color_simple (pixbuf
,
397 dst
= gdk_pixbuf_scale_simple(pixbuf
,
399 GDK_INTERP_BILINEAR
);
401 gdk_draw_pixbuf (g
->drawable
,
405 x
+ g
->x_offset
, y
+ g
->y_offset
,
407 GDK_RGB_DITHER_NORMAL
, 0, 0);
408 gdk_pixbuf_unref (dst
);
412 GdkPixmap
* pixmap
= (GdkPixmap
*)getData (env
, obj
);
413 gdk_draw_drawable (g
->drawable
,
417 x
+ g
->x_offset
, y
+ g
->y_offset
,
421 gdk_threads_leave ();
425 * Draws the pixbuf at x, y, scaled to width and height and
426 * optionally composited and/or flipped with a given background color.
428 JNIEXPORT
void JNICALL
429 Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaledFlipped
430 (JNIEnv
*env
, jobject obj
, jobject gc_obj
,
431 jint bg_red
, jint bg_green
, jint bg_blue
,
432 #if GTK_MINOR_VERSION > 4
433 jboolean flipx
, jboolean flipy
,
435 jboolean flipx
__attribute__((unused
)),
436 jboolean flipy
__attribute__((unused
)),
438 jint srcx
, jint srcy
, jint srcwidth
, jint srcheight
,
439 jint dstx
, jint dsty
, jint dstwidth
, jint dstheight
,
443 GdkPixbuf
*tmp
, *dst
;
447 gdk_threads_enter ();
449 if (srcwidth
<= 0 || srcheight
<= 0
450 || dstwidth
<= 0 || dstheight
<= 0)
452 gdk_threads_leave ();
456 bgColor
= ((bg_red
& 0xFF) << 16) |
457 ((bg_green
& 0xFF) << 8) | (bg_blue
& 0xFF);
459 g
= (struct graphics
*) NSA_GET_G_PTR (env
, gc_obj
);
461 if (!g
|| !GDK_IS_DRAWABLE (g
->drawable
))
463 gdk_threads_leave ();
467 if (offScreen (env
, obj
) == JNI_FALSE
)
469 pixbuf
= (GdkPixbuf
*)getData (env
, obj
);
471 /* Get the source area */
472 tmp
= gdk_pixbuf_new (GDK_COLORSPACE_RGB
,
478 gdk_pixbuf_copy_area (pixbuf
,
482 0, 0); /* dst x , dst y */
484 /* Get a pixbuf from the pixmap */
485 GdkDrawable
*pixmap
= (GdkDrawable
*)getData(env
, obj
);
486 tmp
= gdk_pixbuf_get_from_drawable (NULL
,
488 gdk_drawable_get_colormap( pixmap
),
490 0, 0, /* dst x , dst y */
491 srcwidth
, srcheight
);
494 /* FIXME: This #if should be discarded once I feel comfortable about
495 GTK 2.6 dependence */
496 #if GTK_MINOR_VERSION > 4
497 /* Flip it if necessary. */
498 if (flipx
== JNI_TRUE
)
500 GdkPixbuf
*tmp2
= gdk_pixbuf_flip (tmp
, TRUE
);
501 gdk_pixbuf_unref (tmp
);
504 if (flipy
== JNI_TRUE
)
506 GdkPixbuf
*tmp2
= gdk_pixbuf_flip (tmp
, FALSE
);
507 gdk_pixbuf_unref (tmp
);
512 /* Scale and composite the image */
513 if (composite
== JNI_TRUE
)
514 dst
= gdk_pixbuf_composite_color_simple (tmp
,
523 dst
= gdk_pixbuf_scale_simple(tmp
,
525 GDK_INTERP_BILINEAR
);
526 gdk_pixbuf_unref (tmp
);
528 gdk_draw_pixbuf (g
->drawable
,
532 dstx
+ g
->x_offset
, dsty
+ g
->y_offset
,
534 GDK_RGB_DITHER_NORMAL
, 0, 0);
536 gdk_pixbuf_unref (dst
);
538 gdk_threads_leave ();
542 * Used by GtkFramePeer
544 GdkPixbuf
*cp_gtk_image_get_pixbuf (JNIEnv
*env
, jobject obj
)
552 if (offScreen (env
, obj
) == JNI_FALSE
)
553 return (GdkPixbuf
*)getData (env
, obj
);
555 cls
= (*env
)->GetObjectClass (env
, obj
);
556 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
557 g_assert (field
!= 0);
558 width
= (*env
)->GetIntField (env
, obj
, field
);
560 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
561 g_assert (field
!= 0);
562 height
= (*env
)->GetIntField (env
, obj
, field
);
565 pixmap
= (GdkPixmap
*)getData (env
, obj
);
566 pixbuf
= gdk_pixbuf_get_from_drawable (NULL
,
568 gdk_drawable_get_colormap( pixmap
),
569 0, 0, /* src x , src y */
570 0, 0, /* dst x , dst y */
576 * Used by GdkGraphics
578 GdkPixmap
*cp_gtk_image_get_pixmap (JNIEnv
*env
, jobject obj
)
580 if (offScreen (env
, obj
) == JNI_FALSE
)
582 return (GdkPixmap
*)getData (env
, obj
);
585 jboolean
cp_gtk_image_is_offscreen (JNIEnv
*env
, jobject obj
)
587 return offScreen(env
, obj
);
591 * Maps java.awt.Image scaling hints to the native GDK ones.
593 static GdkInterpType
mapHints(jint hints
)
597 /* For FAST, we use the nearest-neighbor. Fastest and lowest quality. */
599 case SCALE_REPLICATE
:
600 return GDK_INTERP_NEAREST
;
602 /* Hyperbolic for smooth. Slowest too. */
604 return GDK_INTERP_HYPER
;
606 /* the inbetweenish method */
607 case SCALE_AREA_AVERAGING
:
608 return GDK_INTERP_TILES
;
610 /* default to bilinear */
612 return GDK_INTERP_BILINEAR
;
615 /* Sets the width and height fields of a GtkImage object. */
616 static void setWidthHeight (JNIEnv
* env
, jobject obj
, int width
, int height
)
621 cls
= (*env
)->GetObjectClass (env
, obj
);
623 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
624 g_assert (field
!= 0);
625 (*env
)->SetIntField (env
, obj
, field
, (jint
)width
);
627 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
628 g_assert (field
!= 0);
629 (*env
)->SetIntField (env
, obj
, field
, (jint
)height
);
632 /* Returns the value of the offScreen field. */
633 static jboolean
offScreen (JNIEnv
*env
, jobject obj
)
638 cls
= (*env
)->GetObjectClass (env
, obj
);
639 field
= (*env
)->GetFieldID (env
, cls
, "offScreen", "Z");
640 g_assert (field
!= 0);
641 return (*env
)->GetBooleanField (env
, obj
, field
);
644 /* Store and get the pixbuf pointer */
646 createRawData (JNIEnv
* env
, jobject obj
, void *ptr
)
652 cls
= (*env
)->GetObjectClass (env
, obj
);
653 data_fid
= (*env
)->GetFieldID (env
, cls
, "pixmap",
654 "Lgnu/classpath/Pointer;");
655 g_assert (data_fid
!= 0);
657 data
= JCL_NewRawDataObject (env
, ptr
);
659 (*env
)->SetObjectField (env
, obj
, data_fid
, data
);
663 getData (JNIEnv
* env
, jobject obj
)
669 cls
= (*env
)->GetObjectClass (env
, obj
);
670 data_fid
= (*env
)->GetFieldID (env
, cls
, "pixmap",
671 "Lgnu/classpath/Pointer;");
672 g_assert (data_fid
!= 0);
673 data
= (*env
)->GetObjectField (env
, obj
, data_fid
);
675 return JCL_GetRawData (env
, data
);