2 Copyright (C) 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 "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
)
68 /* Don't use the JCL convert function because it throws an exception
70 filename
= (*env
)->GetStringUTFChars (env
, name
, 0);
75 pixbuf
= gdk_pixbuf_new_from_file (filename
, NULL
);
78 (*env
)->ReleaseStringUTFChars (env
, name
, filename
);
82 width
= gdk_pixbuf_get_width (pixbuf
);
83 height
= gdk_pixbuf_get_height (pixbuf
);
85 createRawData (env
, obj
, pixbuf
);
86 setWidthHeight(env
, obj
, width
, height
);
87 (*env
)->ReleaseStringUTFChars (env
, name
, filename
);
93 * Creates the image from an array of java bytes.
95 JNIEXPORT jboolean JNICALL
96 Java_gnu_java_awt_peer_gtk_GtkImage_loadImageFromData
97 (JNIEnv
*env
, jobject obj
, jbyteArray data
)
101 GdkPixbufLoader
* loader
;
106 src
= (*env
)->GetByteArrayElements (env
, data
, NULL
);
107 len
= (*env
)->GetArrayLength (env
, data
);
109 loader
= gdk_pixbuf_loader_new ();
111 gdk_pixbuf_loader_write (loader
, (guchar
*)src
, len
, NULL
);
112 gdk_pixbuf_loader_close (loader
, NULL
);
114 (*env
)->ReleaseByteArrayElements (env
, data
, src
, 0);
116 pixbuf
= gdk_pixbuf_loader_get_pixbuf (loader
);
120 createRawData (env
, obj
, NULL
);
124 width
= gdk_pixbuf_get_width (pixbuf
);
125 height
= gdk_pixbuf_get_height (pixbuf
);
127 createRawData (env
, obj
, pixbuf
);
128 setWidthHeight(env
, obj
, width
, height
);
133 JNIEXPORT
void JNICALL
134 Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf
135 (JNIEnv
*env
, jobject obj
)
138 GdkPixbuf
*pixbuf
= (GdkPixbuf
*) getData (env
, obj
);
139 width
= gdk_pixbuf_get_width (pixbuf
);
140 heigth
= gdk_pixbuf_get_height (pixbuf
);
141 setWidthHeight(env
, obj
, width
, heigth
);
145 * Returns a copy of the pixel data as a java array.
147 JNIEXPORT jintArray JNICALL
148 Java_gnu_java_awt_peer_gtk_GtkImage_getPixels(JNIEnv
*env
, jobject obj
)
151 int width
, height
, rowstride
;
153 jintArray result_array
;
154 jint
*result_array_iter
, *dst
;
157 pixbuf
= cp_gtk_image_get_pixbuf (env
, obj
);
158 width
= gdk_pixbuf_get_width (pixbuf
);
159 height
= gdk_pixbuf_get_height (pixbuf
);
160 rowstride
= gdk_pixbuf_get_rowstride (pixbuf
);
162 result_array
= (*env
)->NewIntArray (env
, (width
* height
));
164 dst
= result_array_iter
=
165 (*env
)->GetIntArrayElements (env
, result_array
, NULL
);
168 pixeldata
= gdk_pixbuf_get_pixels (pixbuf
);
170 g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf
) == 8);
172 if (gdk_pixbuf_get_has_alpha (pixbuf
))
174 for(i
= 0 ; i
< height
; i
++)
176 memcpy(dst
, (void *)pixeldata
, width
* 4);
178 pixeldata
+= rowstride
;
181 for(i
= 0; i
< height
; i
++)
183 for(j
= 0; j
< width
; j
++)
184 dst
[j
] = 0xFF000000 |
185 (pixeldata
[j
*3 + 2] & 0xFF) << 16 |
186 (pixeldata
[j
*3 + 1] & 0xFF) << 8 |
187 (pixeldata
[j
*3] & 0xFF);
189 pixeldata
+= rowstride
;
193 if (offScreen (env
, obj
) == JNI_TRUE
)
194 gdk_pixbuf_unref (pixbuf
);
196 (*env
)->ReleaseIntArrayElements (env
, result_array
, result_array_iter
, 0);
202 * Returns a copy of the pixel data as a java array.
205 JNIEXPORT
void JNICALL
206 Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv
*env
, jobject obj
,
209 GdkPixbuf
*pixbuf
= (GdkPixbuf
*)getData (env
, obj
);
210 int width
, height
, rowstride
;
212 jint
*src_array_iter
, *src
;
215 width
= gdk_pixbuf_get_width (pixbuf
);
216 height
= gdk_pixbuf_get_height (pixbuf
);
217 rowstride
= gdk_pixbuf_get_rowstride (pixbuf
);
219 src
= src_array_iter
=
220 (*env
)->GetIntArrayElements (env
, pixels
, NULL
);
222 pixeldata
= gdk_pixbuf_get_pixels (pixbuf
);
223 for(i
= 0 ; i
< height
; i
++)
225 memcpy((void *)pixeldata
, (void *)src
, width
* 4);
227 pixeldata
+= rowstride
;
230 (*env
)->ReleaseIntArrayElements (env
, pixels
, src_array_iter
, 0);
234 * Allocates a Gtk Pixbuf or Pixmap.
236 JNIEXPORT
void JNICALL
237 Java_gnu_java_awt_peer_gtk_GtkImage_createPixmap(JNIEnv
*env
, jobject obj
)
243 cls
= (*env
)->GetObjectClass (env
, obj
);
244 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
245 g_assert (field
!= 0);
246 width
= (*env
)->GetIntField (env
, obj
, field
);
248 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
249 g_assert (field
!= 0);
250 height
= (*env
)->GetIntField (env
, obj
, field
);
252 if (offScreen (env
, obj
) == JNI_FALSE
)
253 createRawData (env
, obj
, gdk_pixbuf_new (GDK_COLORSPACE_RGB
,
259 createRawData (env
, obj
, gdk_pixmap_new (NULL
, width
, height
,
260 gdk_rgb_get_visual ()->depth
));
264 * Frees the Gtk Pixmap.
266 JNIEXPORT
void JNICALL
267 Java_gnu_java_awt_peer_gtk_GtkImage_freePixmap(JNIEnv
*env
, jobject obj
)
269 if (offScreen (env
, obj
) == JNI_FALSE
)
270 gdk_pixbuf_unref ((GdkPixbuf
*)getData (env
, obj
));
272 g_object_unref ((GdkPixmap
*)getData (env
, obj
));
276 * Sets this pixmap to a scaled version of the source pixmap.
277 * width and height of the destination GtkImage must be set.
279 JNIEXPORT
void JNICALL
280 Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixmap(JNIEnv
*env
,
292 cls
= (*env
)->GetObjectClass (env
, destination
);
293 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
294 g_assert (field
!= 0);
295 width
= (*env
)->GetIntField (env
, destination
, field
);
297 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
298 g_assert (field
!= 0);
299 height
= (*env
)->GetIntField (env
, destination
, field
);
301 pixbuf
= cp_gtk_image_get_pixbuf (env
, source
);
303 dst
= gdk_pixbuf_scale_simple(pixbuf
,
307 if (offScreen (env
, source
) == JNI_TRUE
)
308 gdk_pixbuf_unref (pixbuf
);
310 createRawData (env
, destination
, (void *)dst
);
314 * Draws the pixbuf at x, y, scaled to width and height and
315 * optionally composited with a given background color.
317 JNIEXPORT
void JNICALL
318 Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaled
319 (JNIEnv
*env
, jobject obj
, jobject gc_obj
,
320 jint bg_red
, jint bg_green
, jint bg_blue
,
321 jint x
, jint y
, jint width
, jint height
, jboolean composite
)
327 gdk_threads_enter ();
329 if (width
<= 0 || height
<= 0)
331 gdk_threads_leave ();
335 bgColor
= ((bg_red
& 0xFF) << 16) |
336 ((bg_green
& 0xFF) << 8) | (bg_blue
& 0xFF);
338 g
= (struct graphics
*) NSA_GET_G_PTR (env
, gc_obj
);
340 if (!g
|| !GDK_IS_DRAWABLE (g
->drawable
))
342 gdk_threads_leave ();
346 if (offScreen (env
, obj
) == JNI_FALSE
)
348 GdkPixbuf
* pixbuf
= (GdkPixbuf
*)getData (env
, obj
);
350 /* Scale and composite the image */
351 if (composite
== JNI_TRUE
)
352 dst
= gdk_pixbuf_composite_color_simple (pixbuf
,
361 dst
= gdk_pixbuf_scale_simple(pixbuf
,
363 GDK_INTERP_BILINEAR
);
365 gdk_draw_pixbuf (g
->drawable
,
369 x
+ g
->x_offset
, y
+ g
->y_offset
,
371 GDK_RGB_DITHER_NORMAL
, 0, 0);
372 gdk_pixbuf_unref (dst
);
376 GdkPixmap
* pixmap
= (GdkPixmap
*)getData (env
, obj
);
377 gdk_draw_drawable (g
->drawable
,
381 x
+ g
->x_offset
, y
+ g
->y_offset
,
385 gdk_threads_leave ();
389 * Draws the pixbuf at x, y, scaled to width and height and
390 * optionally composited and/or flipped with a given background color.
392 JNIEXPORT
void JNICALL
393 Java_gnu_java_awt_peer_gtk_GtkImage_drawPixelsScaledFlipped
394 (JNIEnv
*env
, jobject obj
, jobject gc_obj
,
395 jint bg_red
, jint bg_green
, jint bg_blue
,
396 #if GTK_MINOR_VERSION > 4
397 jboolean flipx
, jboolean flipy
,
399 jboolean flipx
__attribute__((unused
)),
400 jboolean flipy
__attribute__((unused
)),
402 jint srcx
, jint srcy
, jint srcwidth
, jint srcheight
,
403 jint dstx
, jint dsty
, jint dstwidth
, jint dstheight
,
407 GdkPixbuf
*tmp
, *dst
;
411 gdk_threads_enter ();
413 if (srcwidth
<= 0 || srcheight
<= 0
414 || dstwidth
<= 0 || dstheight
<= 0)
416 gdk_threads_leave ();
420 bgColor
= ((bg_red
& 0xFF) << 16) |
421 ((bg_green
& 0xFF) << 8) | (bg_blue
& 0xFF);
423 g
= (struct graphics
*) NSA_GET_G_PTR (env
, gc_obj
);
425 if (!g
|| !GDK_IS_DRAWABLE (g
->drawable
))
427 gdk_threads_leave ();
431 if (offScreen (env
, obj
) == JNI_FALSE
)
433 pixbuf
= (GdkPixbuf
*)getData (env
, obj
);
435 /* Get the source area */
436 tmp
= gdk_pixbuf_new (GDK_COLORSPACE_RGB
,
442 gdk_pixbuf_copy_area (pixbuf
,
446 0, 0); /* dst x , dst y */
448 /* Get a pixbuf from the pixmap */
449 GdkDrawable
*pixmap
= (GdkDrawable
*)getData(env
, obj
);
450 tmp
= gdk_pixbuf_get_from_drawable (NULL
,
452 gdk_drawable_get_colormap( pixmap
),
454 0, 0, /* dst x , dst y */
455 srcwidth
, srcheight
);
458 /* FIXME: This #if should be discarded once I feel comfortable about
459 GTK 2.6 dependence */
460 #if GTK_MINOR_VERSION > 4
461 /* Flip it if necessary. */
462 if (flipx
== JNI_TRUE
)
464 GdkPixbuf
*tmp2
= gdk_pixbuf_flip (tmp
, TRUE
);
465 gdk_pixbuf_unref (tmp
);
468 if (flipy
== JNI_TRUE
)
470 GdkPixbuf
*tmp2
= gdk_pixbuf_flip (tmp
, FALSE
);
471 gdk_pixbuf_unref (tmp
);
476 /* Scale and composite the image */
477 if (composite
== JNI_TRUE
)
478 dst
= gdk_pixbuf_composite_color_simple (tmp
,
487 dst
= gdk_pixbuf_scale_simple(tmp
,
489 GDK_INTERP_BILINEAR
);
490 gdk_pixbuf_unref (tmp
);
492 gdk_draw_pixbuf (g
->drawable
,
496 dstx
+ g
->x_offset
, dsty
+ g
->y_offset
,
498 GDK_RGB_DITHER_NORMAL
, 0, 0);
500 gdk_pixbuf_unref (dst
);
502 gdk_threads_leave ();
506 * Used by GtkFramePeer
508 GdkPixbuf
*cp_gtk_image_get_pixbuf (JNIEnv
*env
, jobject obj
)
516 if (offScreen (env
, obj
) == JNI_FALSE
)
517 return (GdkPixbuf
*)getData (env
, obj
);
519 cls
= (*env
)->GetObjectClass (env
, obj
);
520 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
521 g_assert (field
!= 0);
522 width
= (*env
)->GetIntField (env
, obj
, field
);
524 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
525 g_assert (field
!= 0);
526 height
= (*env
)->GetIntField (env
, obj
, field
);
529 pixmap
= (GdkPixmap
*)getData (env
, obj
);
530 pixbuf
= gdk_pixbuf_get_from_drawable (NULL
,
532 gdk_drawable_get_colormap( pixmap
),
533 0, 0, /* src x , src y */
534 0, 0, /* dst x , dst y */
540 * Used by GdkGraphics
542 GdkPixmap
*cp_gtk_image_get_pixmap (JNIEnv
*env
, jobject obj
)
544 if (offScreen (env
, obj
) == JNI_FALSE
)
546 return (GdkPixmap
*)getData (env
, obj
);
549 jboolean
cp_gtk_image_is_offscreen (JNIEnv
*env
, jobject obj
)
551 return offScreen(env
, obj
);
555 * Maps java.awt.Image scaling hints to the native GDK ones.
557 static GdkInterpType
mapHints(jint hints
)
561 /* For FAST, we use the nearest-neighbor. Fastest and lowest quality. */
563 case SCALE_REPLICATE
:
564 return GDK_INTERP_NEAREST
;
566 /* Hyperbolic for smooth. Slowest too. */
568 return GDK_INTERP_HYPER
;
570 /* the inbetweenish method */
571 case SCALE_AREA_AVERAGING
:
572 return GDK_INTERP_TILES
;
574 /* default to bilinear */
576 return GDK_INTERP_BILINEAR
;
579 /* Sets the width and height fields of a GtkImage object. */
580 static void setWidthHeight (JNIEnv
* env
, jobject obj
, int width
, int height
)
585 cls
= (*env
)->GetObjectClass (env
, obj
);
587 field
= (*env
)->GetFieldID (env
, cls
, "width", "I");
588 g_assert (field
!= 0);
589 (*env
)->SetIntField (env
, obj
, field
, (jint
)width
);
591 field
= (*env
)->GetFieldID (env
, cls
, "height", "I");
592 g_assert (field
!= 0);
593 (*env
)->SetIntField (env
, obj
, field
, (jint
)height
);
596 /* Returns the value of the offScreen field. */
597 static jboolean
offScreen (JNIEnv
*env
, jobject obj
)
602 cls
= (*env
)->GetObjectClass (env
, obj
);
603 field
= (*env
)->GetFieldID (env
, cls
, "offScreen", "Z");
604 g_assert (field
!= 0);
605 return (*env
)->GetBooleanField (env
, obj
, field
);
608 /* Store and get the pixbuf pointer */
610 createRawData (JNIEnv
* env
, jobject obj
, void *ptr
)
616 cls
= (*env
)->GetObjectClass (env
, obj
);
617 data_fid
= (*env
)->GetFieldID (env
, cls
, "pixmap",
618 "Lgnu/classpath/Pointer;");
619 g_assert (data_fid
!= 0);
621 data
= JCL_NewRawDataObject (env
, ptr
);
623 (*env
)->SetObjectField (env
, obj
, data_fid
, data
);
627 getData (JNIEnv
* env
, jobject obj
)
633 cls
= (*env
)->GetObjectClass (env
, obj
);
634 data_fid
= (*env
)->GetFieldID (env
, cls
, "pixmap",
635 "Lgnu/classpath/Pointer;");
636 g_assert (data_fid
!= 0);
637 data
= (*env
)->GetObjectField (env
, obj
, data_fid
);
639 return JCL_GetRawData (env
, data
);