Remove old autovect-branch by moving to "dead" directory.
[official-gcc.git] / old-autovect-branch / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkImage.c
blobae065763688f7cefa2b8c8363f04b2f872b89518
1 /* gtkimage.c
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)
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 gdk_threads_enter ();
70 /* Don't use the JCL convert function because it throws an exception
71 on failure */
72 filename = (*env)->GetStringUTFChars (env, name, 0);
74 if (filename == NULL)
76 gdk_threads_leave ();
77 return JNI_FALSE;
80 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
81 if (pixbuf == NULL)
83 (*env)->ReleaseStringUTFChars (env, name, filename);
84 gdk_threads_leave ();
85 return JNI_FALSE;
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);
95 gdk_threads_leave ();
97 return JNI_TRUE;
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)
107 jbyte *src;
108 GdkPixbuf* pixbuf;
109 GdkPixbufLoader* loader;
110 int len;
111 int width;
112 int height;
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);
128 if (pixbuf == NULL)
130 createRawData (env, obj, NULL);
132 gdk_threads_leave ();
134 return JNI_FALSE;
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 ();
145 return JNI_TRUE;
148 JNIEXPORT void JNICALL
149 Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf
150 (JNIEnv *env, jobject obj)
152 int width, heigth;
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)
167 GdkPixbuf *pixbuf;
168 int width, height, rowstride;
169 guchar *pixeldata;
170 jintArray result_array;
171 jint *result_array_iter, *dst;
172 int i,j;
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);
196 dst += width;
197 pixeldata += rowstride;
199 } else {
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);
207 dst += width;
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 ();
219 return result_array;
223 * Returns a copy of the pixel data as a java array.
224 * (GdkPixbuf only)
226 JNIEXPORT void JNICALL
227 Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj,
228 jintArray pixels)
230 GdkPixbuf *pixbuf = (GdkPixbuf *)getData (env, obj);
231 int width, height, rowstride;
232 guchar *pixeldata;
233 jint *src_array_iter, *src;
234 int i;
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);
249 src += width;
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)
264 int width, height;
265 jclass cls;
266 jfieldID field;
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,
281 TRUE,
283 width,
284 height));
285 else
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));
301 else
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,
313 jobject destination,
314 jobject source,
315 jint hints)
317 GdkPixbuf* dst;
318 int width, height;
319 jclass cls;
320 jfieldID field;
322 GdkPixbuf *pixbuf;
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,
338 width, height,
339 mapHints(hints));
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)
359 GdkPixbuf* dst;
360 struct graphics *g;
361 guint32 bgColor;
363 gdk_threads_enter ();
365 if (width <= 0 || height <= 0)
367 gdk_threads_leave ();
368 return;
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 ();
379 return;
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,
389 width,
390 height,
391 GDK_INTERP_BILINEAR,
392 255,
393 width,
394 bgColor,
395 bgColor);
396 else
397 dst = gdk_pixbuf_scale_simple(pixbuf,
398 width, height,
399 GDK_INTERP_BILINEAR);
401 gdk_draw_pixbuf (g->drawable,
402 g->gc,
403 dst,
404 0, 0,
405 x + g->x_offset, y + g->y_offset,
406 width, height,
407 GDK_RGB_DITHER_NORMAL, 0, 0);
408 gdk_pixbuf_unref (dst);
410 } else {
411 /* Get a pixmap */
412 GdkPixmap* pixmap = (GdkPixmap *)getData (env, obj);
413 gdk_draw_drawable (g->drawable,
414 g->gc,
415 pixmap,
416 0, 0, /* src x,y */
417 x + g->x_offset, y + g->y_offset,
418 width, height);
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,
434 #else
435 jboolean flipx __attribute__((unused)),
436 jboolean flipy __attribute__((unused)),
437 #endif
438 jint srcx, jint srcy, jint srcwidth, jint srcheight,
439 jint dstx, jint dsty, jint dstwidth, jint dstheight,
440 jboolean composite)
442 GdkPixbuf *pixbuf;
443 GdkPixbuf *tmp, *dst;
444 struct graphics *g;
445 guint32 bgColor;
447 gdk_threads_enter ();
449 if (srcwidth <= 0 || srcheight <= 0
450 || dstwidth <= 0 || dstheight <= 0)
452 gdk_threads_leave ();
453 return;
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 ();
464 return;
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,
473 TRUE,
475 srcwidth,
476 srcheight);
478 gdk_pixbuf_copy_area (pixbuf,
479 srcx, srcy,
480 srcwidth, srcheight,
481 tmp,
482 0, 0); /* dst x , dst y */
483 } else {
484 /* Get a pixbuf from the pixmap */
485 GdkDrawable *pixmap = (GdkDrawable *)getData(env, obj);
486 tmp = gdk_pixbuf_get_from_drawable (NULL,
487 pixmap,
488 gdk_drawable_get_colormap( pixmap ),
489 srcx, srcy,
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);
502 tmp = tmp2;
504 if (flipy == JNI_TRUE)
506 GdkPixbuf *tmp2 = gdk_pixbuf_flip (tmp, FALSE);
507 gdk_pixbuf_unref (tmp);
508 tmp = tmp2;
510 #endif
512 /* Scale and composite the image */
513 if (composite == JNI_TRUE)
514 dst = gdk_pixbuf_composite_color_simple (tmp,
515 dstwidth,
516 dstheight,
517 GDK_INTERP_BILINEAR,
518 255,
519 dstwidth,
520 bgColor,
521 bgColor);
522 else
523 dst = gdk_pixbuf_scale_simple(tmp,
524 dstwidth, dstheight,
525 GDK_INTERP_BILINEAR);
526 gdk_pixbuf_unref (tmp);
528 gdk_draw_pixbuf (g->drawable,
529 g->gc,
530 dst,
531 0, 0,
532 dstx + g->x_offset, dsty + g->y_offset,
533 dstwidth, dstheight,
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)
546 int width, height;
547 GdkPixbuf *pixbuf;
548 GdkPixmap* pixmap;
549 jclass cls;
550 jfieldID field;
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);
564 /* Get a pixmap */
565 pixmap = (GdkPixmap *)getData (env, obj);
566 pixbuf = gdk_pixbuf_get_from_drawable (NULL,
567 pixmap,
568 gdk_drawable_get_colormap( pixmap ),
569 0, 0, /* src x , src y */
570 0, 0, /* dst x , dst y */
571 width, height);
572 return pixbuf;
576 * Used by GdkGraphics
578 GdkPixmap *cp_gtk_image_get_pixmap (JNIEnv *env, jobject obj)
580 if (offScreen (env, obj) == JNI_FALSE)
581 return NULL;
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)
595 switch ( hints )
597 /* For FAST, we use the nearest-neighbor. Fastest and lowest quality. */
598 case SCALE_FAST:
599 case SCALE_REPLICATE:
600 return GDK_INTERP_NEAREST;
602 /* Hyperbolic for smooth. Slowest too. */
603 case SCALE_SMOOTH:
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)
618 jclass cls;
619 jfieldID field;
621 cls = (*env)->GetObjectClass (env, obj);
622 g_assert (cls != 0);
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)
635 jclass cls;
636 jfieldID field;
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 */
645 static void
646 createRawData (JNIEnv * env, jobject obj, void *ptr)
648 jclass cls;
649 jobject data;
650 jfieldID data_fid;
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);
662 static void *
663 getData (JNIEnv * env, jobject obj)
665 jclass cls;
666 jfieldID data_fid;
667 jobject data;
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);