summaryrefslogtreecommitdiff
path: root/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c')
-rw-r--r--libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c
new file mode 100644
index 000000000..c2fbba212
--- /dev/null
+++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkImage.c
@@ -0,0 +1,434 @@
+/* gtkimage.c
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+#include "jcl.h"
+#include "gtkpeer.h"
+
+#include "gnu_java_awt_peer_gtk_GtkImage.h"
+
+/* The constant fields in java.awt.Image */
+#define SCALE_DEFAULT 1
+#define SCALE_FAST 2
+#define SCALE_SMOOTH 4
+#define SCALE_REPLICATE 8
+#define SCALE_AREA_AVERAGING 16
+
+/* local stuff */
+static GdkInterpType mapHints(jint hints);
+static void createRawData (JNIEnv * env, jobject obj, void *ptr);
+static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height);
+
+/**
+ * Loads a pixbuf from a file.
+ */
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_loadPixbuf
+ (JNIEnv *env, jobject obj, jstring name)
+{
+ const char *filename;
+ int width, height;
+ GdkPixbuf *pixbuf;
+
+ /* Don't use the JCL convert function because it throws an exception
+ on failure */
+ filename = (*env)->GetStringUTFChars (env, name, 0);
+
+ if (filename == NULL)
+ return JNI_FALSE;
+
+ pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+ if (pixbuf == NULL)
+ {
+ (*env)->ReleaseStringUTFChars (env, name, filename);
+ return JNI_FALSE;
+ }
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ createRawData (env, obj, pixbuf);
+ setWidthHeight(env, obj, width, height);
+ (*env)->ReleaseStringUTFChars (env, name, filename);
+
+ return JNI_TRUE;
+}
+
+/*
+ * Creates the image from an array of java bytes.
+ */
+JNIEXPORT jboolean JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_loadImageFromData
+ (JNIEnv *env, jobject obj, jbyteArray data)
+{
+ jbyte *src;
+ GdkPixbuf* pixbuf;
+ GdkPixbufLoader* loader;
+ int len;
+ int width;
+ int height;
+
+ src = (*env)->GetByteArrayElements (env, data, NULL);
+ len = (*env)->GetArrayLength (env, data);
+
+ loader = gdk_pixbuf_loader_new ();
+
+ gdk_pixbuf_loader_write (loader, (guchar *)src, len, NULL);
+ gdk_pixbuf_loader_close (loader, NULL);
+
+ (*env)->ReleaseByteArrayElements (env, data, src, 0);
+
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+
+ if (pixbuf == NULL)
+ {
+ g_object_unref (loader);
+ createRawData (env, obj, NULL);
+ return JNI_FALSE;
+ }
+
+ g_object_ref (pixbuf);
+ g_object_unref (loader);
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ createRawData (env, obj, pixbuf);
+ setWidthHeight(env, obj, width, height);
+
+ return JNI_TRUE;
+}
+
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf
+(JNIEnv *env, jobject obj)
+{
+ int width, heigth;
+ GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj);
+ width = gdk_pixbuf_get_width (pixbuf);
+ heigth = gdk_pixbuf_get_height (pixbuf);
+ setWidthHeight(env, obj, width, heigth);
+}
+
+/**
+ * Returns a copy of the pixel data as a java array.
+ */
+JNIEXPORT jintArray JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_getPixels(JNIEnv *env, jobject obj)
+{
+ GdkPixbuf *pixbuf;
+ int width, height, rowstride;
+ guchar *pixeldata;
+ jintArray result_array;
+ jint *result_array_iter, *dst;
+ int i,j;
+
+ gdk_threads_enter ();
+
+ pixbuf = cp_gtk_image_get_pixbuf (env, obj);
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+ result_array = (*env)->NewIntArray (env, (width * height));
+ if (result_array == NULL)
+ {
+ gdk_threads_leave ();
+ return NULL;
+ }
+
+ dst = result_array_iter =
+ (*env)->GetIntArrayElements (env, result_array, NULL);
+
+
+ pixeldata = gdk_pixbuf_get_pixels (pixbuf);
+
+ g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
+
+ if (gdk_pixbuf_get_has_alpha (pixbuf))
+ {
+ for(i = 0 ; i < height; i++)
+ {
+ memcpy(dst, (void *)pixeldata, width * 4);
+ dst += width;
+ pixeldata += rowstride;
+ }
+ } else {
+
+ /* Add a default alpha value of 0xFF to the pixeldata without alpha
+ information and keep it in the same format as the pixeldata with alpha
+ information. On Little Endian systems: AABBGGRR and on Big Endian
+ systems: RRGGBBAA. */
+
+ for(i = 0; i < height; i++)
+ {
+ for(j = 0; j < width; j++)
+
+#ifndef WORDS_BIGENDIAN
+ dst[j] = 0xFF000000
+ | (pixeldata[j*3 + 2] & 0xFF) << 16
+ | (pixeldata[j*3 + 1] & 0xFF) << 8
+ | (pixeldata[j*3] & 0xFF);
+#else
+ dst[j] = (pixeldata[j*3] & 0xFF) << 24
+ | (pixeldata[j*3 + 1] & 0xFF) << 16
+ | (pixeldata[j*3 + 2] & 0xFF) << 8
+ | 0xFF;
+#endif
+ dst += width;
+ pixeldata += rowstride;
+ }
+ }
+
+ (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0);
+
+ gdk_threads_leave ();
+ return result_array;
+}
+
+/**
+ * Returns a copy of the pixel data as a java array.
+ * (GdkPixbuf only)
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj,
+ jintArray pixels)
+{
+ GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj);
+ int width, height, rowstride;
+ guchar *pixeldata;
+ jint *src_array_iter, *src;
+ int i;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+
+ src = src_array_iter =
+ (*env)->GetIntArrayElements (env, pixels, NULL);
+
+ pixeldata = gdk_pixbuf_get_pixels (pixbuf);
+ for(i = 0 ; i < height; i++)
+ {
+ memcpy((void *)pixeldata, (void *)src, width * 4);
+ src += width;
+ pixeldata += rowstride;
+ }
+
+ (*env)->ReleaseIntArrayElements (env, pixels, src_array_iter, 0);
+}
+
+/**
+ * Allocates a Gtk Pixbuf
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_createPixbuf(JNIEnv *env, jobject obj)
+{
+ int width, height;
+ jclass cls;
+ jfieldID field;
+
+ cls = (*env)->GetObjectClass (env, obj);
+ field = (*env)->GetFieldID (env, cls, "width", "I");
+ g_assert (field != 0);
+ width = (*env)->GetIntField (env, obj, field);
+
+ field = (*env)->GetFieldID (env, cls, "height", "I");
+ g_assert (field != 0);
+ height = (*env)->GetIntField (env, obj, field);
+
+ createRawData (env, obj, gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+ TRUE,
+ 8,
+ width,
+ height));
+}
+
+/**
+ * Allocates a Gtk Pixbuf
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_initFromBuffer(JNIEnv *env, jobject obj,
+ jlong bufferPointer)
+{
+ int width, height;
+ jclass cls;
+ jfieldID field;
+ GdkPixbuf *pixbuf;
+ const guchar *bp = JLONG_TO_PTR(const guchar, bufferPointer);
+
+ g_assert(bp != NULL);
+ cls = (*env)->GetObjectClass( env, obj );
+ field = (*env)->GetFieldID( env, cls, "width", "I" );
+ g_assert( field != 0 );
+ width = (*env)->GetIntField( env, obj, field );
+
+ field = (*env)->GetFieldID( env, cls, "height", "I" );
+ g_assert( field != 0 );
+ height = (*env)->GetIntField( env, obj, field );
+
+ pixbuf = gdk_pixbuf_new_from_data( bp,
+ GDK_COLORSPACE_RGB, TRUE, 8,
+ width, height, width * 4, NULL, NULL );
+ g_assert( pixbuf != NULL );
+ createRawData( env, obj, pixbuf );
+}
+
+/**
+ * Frees the Gtk Pixbuf.
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_freePixbuf(JNIEnv *env, jobject obj)
+{
+ gdk_pixbuf_unref (cp_gtk_image_get_pixbuf (env, obj));
+}
+
+/**
+ * Sets this to a scaled version of the original pixbuf
+ * width and height of the destination GtkImage must be set.
+ */
+JNIEXPORT void JNICALL
+Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixbuf(JNIEnv *env,
+ jobject destination,
+ jobject source,
+ jint hints)
+{
+ GdkPixbuf* dst;
+ int width, height;
+ jclass cls;
+ jfieldID field;
+
+ GdkPixbuf *pixbuf;
+
+ cls = (*env)->GetObjectClass (env, destination);
+ field = (*env)->GetFieldID (env, cls, "width", "I");
+ g_assert (field != 0);
+ width = (*env)->GetIntField (env, destination, field);
+
+ field = (*env)->GetFieldID (env, cls, "height", "I");
+ g_assert (field != 0);
+ height = (*env)->GetIntField (env, destination, field);
+
+ pixbuf = cp_gtk_image_get_pixbuf (env, source);
+
+ dst = gdk_pixbuf_scale_simple(pixbuf,
+ width, height,
+ mapHints(hints));
+
+ createRawData (env, destination, (void *)dst);
+}
+
+/**
+ * Used by GtkFramePeer
+ */
+GdkPixbuf *cp_gtk_image_get_pixbuf (JNIEnv *env, jobject obj)
+{
+ jclass cls;
+ jfieldID data_fid;
+ jobject data;
+
+ cls = (*env)->GetObjectClass (env, obj);
+ data_fid = (*env)->GetFieldID (env, cls, "pixbuf",
+ "Lgnu/classpath/Pointer;");
+ g_assert (data_fid != 0);
+ data = (*env)->GetObjectField (env, obj, data_fid);
+
+ if (data == NULL)
+ return NULL;
+
+ return (GdkPixbuf *)JCL_GetRawData (env, data);
+}
+
+/**
+ * Maps java.awt.Image scaling hints to the native GDK ones.
+ */
+static GdkInterpType mapHints(jint hints)
+{
+ switch ( hints )
+ {
+ /* For FAST, we use the nearest-neighbor. Fastest and lowest quality. */
+ case SCALE_FAST:
+ case SCALE_REPLICATE:
+ return GDK_INTERP_NEAREST;
+
+ /* Hyperbolic for smooth. Slowest too. */
+ case SCALE_SMOOTH:
+ return GDK_INTERP_HYPER;
+
+ /* the inbetweenish method */
+ case SCALE_AREA_AVERAGING:
+ return GDK_INTERP_TILES;
+
+ /* default to bilinear */
+ }
+ return GDK_INTERP_BILINEAR;
+}
+
+/* Sets the width and height fields of a GtkImage object. */
+static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height)
+{
+ jclass cls;
+ jfieldID field;
+
+ cls = (*env)->GetObjectClass (env, obj);
+ g_assert (cls != 0);
+ field = (*env)->GetFieldID (env, cls, "width", "I");
+ g_assert (field != 0);
+ (*env)->SetIntField (env, obj, field, (jint)width);
+
+ field = (*env)->GetFieldID (env, cls, "height", "I");
+ g_assert (field != 0);
+ (*env)->SetIntField (env, obj, field, (jint)height);
+}
+
+/* Store and get the pixbuf pointer */
+static void
+createRawData (JNIEnv * env, jobject obj, void *ptr)
+{
+ jclass cls;
+ jobject data;
+ jfieldID data_fid;
+
+ cls = (*env)->GetObjectClass (env, obj);
+ data_fid = (*env)->GetFieldID (env, cls, "pixbuf",
+ "Lgnu/classpath/Pointer;");
+ g_assert (data_fid != 0);
+
+ data = JCL_NewRawDataObject (env, ptr);
+
+ (*env)->SetObjectField (env, obj, data_fid, data);
+}
+