Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkImage.c
blob92bc09edde7630b8d20a27000503af9a3312f5ab
1 /* gtkimage.c
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)
9 any later version.
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
19 02110-1301 USA.
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
24 combination.
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. */
38 #include "jcl.h"
39 #include "gtkpeer.h"
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
45 #define SCALE_FAST 2
46 #define SCALE_SMOOTH 4
47 #define SCALE_REPLICATE 8
48 #define SCALE_AREA_AVERAGING 16
50 /* local stuff */
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);
57 /**
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)
64 const char *filename;
65 int width, height;
66 GdkPixbuf *pixbuf;
68 /* Don't use the JCL convert function because it throws an exception
69 on failure */
70 filename = (*env)->GetStringUTFChars (env, name, 0);
72 if (filename == NULL)
73 return JNI_FALSE;
75 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
76 if (pixbuf == NULL)
78 (*env)->ReleaseStringUTFChars (env, name, filename);
79 return JNI_FALSE;
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);
89 return JNI_TRUE;
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)
99 jbyte *src;
100 GdkPixbuf* pixbuf;
101 GdkPixbufLoader* loader;
102 int len;
103 int width;
104 int height;
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);
118 if (pixbuf == NULL)
120 createRawData (env, obj, NULL);
121 return JNI_FALSE;
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);
130 return JNI_TRUE;
133 JNIEXPORT void JNICALL
134 Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf
135 (JNIEnv *env, jobject obj)
137 int width, heigth;
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)
150 GdkPixbuf *pixbuf;
151 int width, height, rowstride;
152 guchar *pixeldata;
153 jintArray result_array;
154 jint *result_array_iter, *dst;
155 int i,j;
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);
177 dst += width;
178 pixeldata += rowstride;
180 } else {
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);
188 dst += width;
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);
198 return result_array;
202 * Returns a copy of the pixel data as a java array.
203 * (GdkPixbuf only)
205 JNIEXPORT void JNICALL
206 Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj,
207 jintArray pixels)
209 GdkPixbuf *pixbuf = (GdkPixbuf *)getData (env, obj);
210 int width, height, rowstride;
211 guchar *pixeldata;
212 jint *src_array_iter, *src;
213 int i;
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);
226 src += width;
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)
239 int width, height;
240 jclass cls;
241 jfieldID field;
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,
254 TRUE,
256 width,
257 height));
258 else
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));
271 else
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,
281 jobject destination,
282 jobject source,
283 jint hints)
285 GdkPixbuf* dst;
286 int width, height;
287 jclass cls;
288 jfieldID field;
290 GdkPixbuf *pixbuf;
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,
304 width, height,
305 mapHints(hints));
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)
323 GdkPixbuf* dst;
324 struct graphics *g;
325 guint32 bgColor;
327 gdk_threads_enter ();
329 if (width <= 0 || height <= 0)
331 gdk_threads_leave ();
332 return;
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 ();
343 return;
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,
353 width,
354 height,
355 GDK_INTERP_BILINEAR,
356 255,
357 width,
358 bgColor,
359 bgColor);
360 else
361 dst = gdk_pixbuf_scale_simple(pixbuf,
362 width, height,
363 GDK_INTERP_BILINEAR);
365 gdk_draw_pixbuf (g->drawable,
366 g->gc,
367 dst,
368 0, 0,
369 x + g->x_offset, y + g->y_offset,
370 width, height,
371 GDK_RGB_DITHER_NORMAL, 0, 0);
372 gdk_pixbuf_unref (dst);
374 } else {
375 /* Get a pixmap */
376 GdkPixmap* pixmap = (GdkPixmap *)getData (env, obj);
377 gdk_draw_drawable (g->drawable,
378 g->gc,
379 pixmap,
380 0, 0, /* src x,y */
381 x + g->x_offset, y + g->y_offset,
382 width, height);
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,
398 #else
399 jboolean flipx __attribute__((unused)),
400 jboolean flipy __attribute__((unused)),
401 #endif
402 jint srcx, jint srcy, jint srcwidth, jint srcheight,
403 jint dstx, jint dsty, jint dstwidth, jint dstheight,
404 jboolean composite)
406 GdkPixbuf *pixbuf;
407 GdkPixbuf *tmp, *dst;
408 struct graphics *g;
409 guint32 bgColor;
411 gdk_threads_enter ();
413 if (srcwidth <= 0 || srcheight <= 0
414 || dstwidth <= 0 || dstheight <= 0)
416 gdk_threads_leave ();
417 return;
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 ();
428 return;
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,
437 TRUE,
439 srcwidth,
440 srcheight);
442 gdk_pixbuf_copy_area (pixbuf,
443 srcx, srcy,
444 srcwidth, srcheight,
445 tmp,
446 0, 0); /* dst x , dst y */
447 } else {
448 /* Get a pixbuf from the pixmap */
449 GdkDrawable *pixmap = (GdkDrawable *)getData(env, obj);
450 tmp = gdk_pixbuf_get_from_drawable (NULL,
451 pixmap,
452 gdk_drawable_get_colormap( pixmap ),
453 srcx, srcy,
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);
466 tmp = tmp2;
468 if (flipy == JNI_TRUE)
470 GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, FALSE);
471 gdk_pixbuf_unref (tmp);
472 tmp = tmp2;
474 #endif
476 /* Scale and composite the image */
477 if (composite == JNI_TRUE)
478 dst = gdk_pixbuf_composite_color_simple (tmp,
479 dstwidth,
480 dstheight,
481 GDK_INTERP_BILINEAR,
482 255,
483 dstwidth,
484 bgColor,
485 bgColor);
486 else
487 dst = gdk_pixbuf_scale_simple(tmp,
488 dstwidth, dstheight,
489 GDK_INTERP_BILINEAR);
490 gdk_pixbuf_unref (tmp);
492 gdk_draw_pixbuf (g->drawable,
493 g->gc,
494 dst,
495 0, 0,
496 dstx + g->x_offset, dsty + g->y_offset,
497 dstwidth, dstheight,
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)
510 int width, height;
511 GdkPixbuf *pixbuf;
512 GdkPixmap* pixmap;
513 jclass cls;
514 jfieldID field;
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);
528 /* Get a pixmap */
529 pixmap = (GdkPixmap *)getData (env, obj);
530 pixbuf = gdk_pixbuf_get_from_drawable (NULL,
531 pixmap,
532 gdk_drawable_get_colormap( pixmap ),
533 0, 0, /* src x , src y */
534 0, 0, /* dst x , dst y */
535 width, height);
536 return pixbuf;
540 * Used by GdkGraphics
542 GdkPixmap *cp_gtk_image_get_pixmap (JNIEnv *env, jobject obj)
544 if (offScreen (env, obj) == JNI_FALSE)
545 return NULL;
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)
559 switch ( hints )
561 /* For FAST, we use the nearest-neighbor. Fastest and lowest quality. */
562 case SCALE_FAST:
563 case SCALE_REPLICATE:
564 return GDK_INTERP_NEAREST;
566 /* Hyperbolic for smooth. Slowest too. */
567 case SCALE_SMOOTH:
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)
582 jclass cls;
583 jfieldID field;
585 cls = (*env)->GetObjectClass (env, obj);
586 g_assert (cls != 0);
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)
599 jclass cls;
600 jfieldID field;
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 */
609 static void
610 createRawData (JNIEnv * env, jobject obj, void *ptr)
612 jclass cls;
613 jobject data;
614 jfieldID data_fid;
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);
626 static void *
627 getData (JNIEnv * env, jobject obj)
629 jclass cls;
630 jfieldID data_fid;
631 jobject data;
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);