OSDN Git Service

2008-11-10 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libjava / classpath / native / jni / gtk-peer / gnu_java_awt_peer_gtk_GtkImage.c
1 /* gtkimage.c
2    Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
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.
10
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.
15
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.
20
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.
25
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. */
37
38 #include "jcl.h"
39 #include "gtkpeer.h"
40
41 #include "gnu_java_awt_peer_gtk_GtkImage.h"
42
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
49
50 /* local stuff */
51 static GdkInterpType mapHints(jint hints);
52 static void createRawData (JNIEnv * env, jobject obj, void *ptr);
53 static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height);
54
55 /**
56  * Loads a pixbuf from a file.
57  */
58 JNIEXPORT jboolean JNICALL
59 Java_gnu_java_awt_peer_gtk_GtkImage_loadPixbuf
60   (JNIEnv *env, jobject obj, jstring name)
61 {
62   const char *filename;
63   int width, height;
64   GdkPixbuf *pixbuf;
65
66   /* Don't use the JCL convert function because it throws an exception
67      on failure */
68   filename = (*env)->GetStringUTFChars (env, name, 0);
69
70   if (filename == NULL)
71     return JNI_FALSE;
72
73   pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
74   if (pixbuf == NULL)
75     {
76       (*env)->ReleaseStringUTFChars (env, name, filename);
77       return JNI_FALSE;
78     }
79
80   width =  gdk_pixbuf_get_width (pixbuf);
81   height = gdk_pixbuf_get_height (pixbuf);
82   
83   createRawData (env, obj, pixbuf);
84   setWidthHeight(env, obj, width, height);
85   (*env)->ReleaseStringUTFChars (env, name, filename);
86
87   return JNI_TRUE;
88 }
89
90 /*
91  * Creates the image from an array of java bytes.
92  */
93 JNIEXPORT jboolean JNICALL
94 Java_gnu_java_awt_peer_gtk_GtkImage_loadImageFromData
95   (JNIEnv *env, jobject obj, jbyteArray data)
96 {
97   jbyte *src;
98   GdkPixbuf* pixbuf;
99   GdkPixbufLoader* loader;
100   int len;
101   int width;
102   int height;
103
104   src = (*env)->GetByteArrayElements (env, data, NULL);
105   len = (*env)->GetArrayLength (env, data);
106
107   loader = gdk_pixbuf_loader_new ();
108
109   gdk_pixbuf_loader_write (loader, (guchar *)src, len, NULL);
110   gdk_pixbuf_loader_close (loader, NULL);
111
112   (*env)->ReleaseByteArrayElements (env, data, src, 0);
113
114   pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
115
116   if (pixbuf == NULL)
117     {
118       g_object_unref (loader);
119       createRawData (env, obj, NULL);
120       return JNI_FALSE;
121     }
122
123   g_object_ref (pixbuf);
124   g_object_unref (loader);
125
126   width =  gdk_pixbuf_get_width (pixbuf);
127   height = gdk_pixbuf_get_height (pixbuf);
128
129   createRawData (env, obj, pixbuf);
130   setWidthHeight(env, obj, width, height);
131
132   return JNI_TRUE;
133 }
134
135 JNIEXPORT void JNICALL
136 Java_gnu_java_awt_peer_gtk_GtkImage_createFromPixbuf
137 (JNIEnv *env, jobject obj)
138 {
139   int width, heigth;
140   GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj);
141   width =  gdk_pixbuf_get_width (pixbuf);
142   heigth = gdk_pixbuf_get_height (pixbuf);
143   setWidthHeight(env, obj, width, heigth);
144 }
145
146 /**
147  * Returns a copy of the pixel data as a java array.
148  */
149 JNIEXPORT jintArray JNICALL 
150 Java_gnu_java_awt_peer_gtk_GtkImage_getPixels(JNIEnv *env, jobject obj)
151 {
152   GdkPixbuf *pixbuf;
153   int width, height, rowstride;
154   guchar *pixeldata;
155   jintArray result_array;
156   jint *result_array_iter, *dst;
157   int i,j;
158
159   gdk_threads_enter ();
160
161   pixbuf = cp_gtk_image_get_pixbuf (env, obj);
162   width =  gdk_pixbuf_get_width (pixbuf);
163   height = gdk_pixbuf_get_height (pixbuf);
164   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
165
166   result_array = (*env)->NewIntArray (env, (width * height));
167   if (result_array == NULL)
168     {
169       gdk_threads_leave ();
170       return NULL;
171     }
172
173   dst = result_array_iter = 
174     (*env)->GetIntArrayElements (env, result_array, NULL);
175
176
177   pixeldata = gdk_pixbuf_get_pixels (pixbuf);
178
179   g_assert (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
180
181   if (gdk_pixbuf_get_has_alpha (pixbuf))
182     {
183       for(i = 0 ; i < height; i++)
184         {
185           memcpy(dst, (void *)pixeldata, width * 4);
186           dst += width;
187           pixeldata += rowstride;
188         }
189     } else {
190
191     /* Add a default alpha value of 0xFF to the pixeldata without alpha
192        information and keep it in the same format as the pixeldata with alpha
193        information. On Little Endian systems: AABBGGRR and on Big Endian
194        systems: RRGGBBAA.  */
195
196       for(i = 0; i < height; i++)
197         {
198           for(j = 0; j < width; j++)
199
200 #ifndef WORDS_BIGENDIAN
201             dst[j] = 0xFF000000
202               | (pixeldata[j*3 + 2] & 0xFF) << 16
203               | (pixeldata[j*3 + 1] & 0xFF) << 8
204               | (pixeldata[j*3] & 0xFF);
205 #else
206             dst[j] = (pixeldata[j*3] & 0xFF) << 24
207               | (pixeldata[j*3 + 1] & 0xFF) << 16
208               | (pixeldata[j*3 + 2] & 0xFF) << 8
209               | 0xFF;
210 #endif
211           dst += width;
212           pixeldata += rowstride;
213         }
214     }
215   
216   (*env)->ReleaseIntArrayElements (env, result_array, result_array_iter, 0);
217     
218   gdk_threads_leave ();
219   return result_array;
220 }
221
222 /**
223  * Returns a copy of the pixel data as a java array.
224  * (GdkPixbuf only)
225  */
226 JNIEXPORT void JNICALL 
227 Java_gnu_java_awt_peer_gtk_GtkImage_setPixels(JNIEnv *env, jobject obj,
228                                               jintArray pixels)
229 {
230   GdkPixbuf *pixbuf = cp_gtk_image_get_pixbuf (env, obj);
231   int width, height, rowstride;
232   guchar *pixeldata;
233   jint *src_array_iter, *src;
234   int i;
235
236   width =  gdk_pixbuf_get_width (pixbuf);
237   height = gdk_pixbuf_get_height (pixbuf);
238   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
239
240   src = src_array_iter = 
241     (*env)->GetIntArrayElements (env, pixels, NULL);
242
243   pixeldata = gdk_pixbuf_get_pixels (pixbuf);
244   for(i = 0 ; i < height; i++)
245     {
246       memcpy((void *)pixeldata, (void *)src, width * 4);
247       src += width;
248       pixeldata += rowstride;
249     }
250
251   (*env)->ReleaseIntArrayElements (env, pixels, src_array_iter, 0);
252 }
253
254 /**
255  * Allocates a Gtk Pixbuf 
256  */
257 JNIEXPORT void JNICALL
258 Java_gnu_java_awt_peer_gtk_GtkImage_createPixbuf(JNIEnv *env, jobject obj)
259 {
260   int width, height;
261   jclass cls;
262   jfieldID field;
263
264   cls = (*env)->GetObjectClass (env, obj);
265   field = (*env)->GetFieldID (env, cls, "width", "I");
266   g_assert (field != 0);
267   width = (*env)->GetIntField (env, obj, field);
268
269   field = (*env)->GetFieldID (env, cls, "height", "I");
270   g_assert (field != 0);
271   height = (*env)->GetIntField (env, obj, field);
272
273   createRawData (env, obj, gdk_pixbuf_new (GDK_COLORSPACE_RGB, 
274                                            TRUE,
275                                            8,
276                                            width,
277                                            height));
278 }
279
280 /**
281  * Allocates a Gtk Pixbuf 
282  */
283 JNIEXPORT void JNICALL
284 Java_gnu_java_awt_peer_gtk_GtkImage_initFromBuffer(JNIEnv *env, jobject obj,
285                                                    jlong bufferPointer)
286 {
287   int width, height;
288   jclass cls;
289   jfieldID field;
290   GdkPixbuf *pixbuf;
291   const guchar *bp = JLONG_TO_PTR(const guchar, bufferPointer);
292
293   g_assert(bp != NULL);
294   cls = (*env)->GetObjectClass( env, obj );
295   field = (*env)->GetFieldID( env, cls, "width", "I" );
296   g_assert( field != 0 );
297   width = (*env)->GetIntField( env, obj, field );
298
299   field = (*env)->GetFieldID( env, cls, "height", "I" );
300   g_assert( field != 0 );
301   height = (*env)->GetIntField( env, obj, field );
302
303   pixbuf = gdk_pixbuf_new_from_data( bp,
304                                      GDK_COLORSPACE_RGB, TRUE, 8,
305                                      width, height, width * 4, NULL, NULL );
306   g_assert( pixbuf != NULL );
307   createRawData( env, obj, pixbuf );
308 }
309
310 /**
311  * Frees the Gtk Pixbuf.
312  */
313 JNIEXPORT void JNICALL
314 Java_gnu_java_awt_peer_gtk_GtkImage_freePixbuf(JNIEnv *env, jobject obj)
315 {
316   gdk_pixbuf_unref (cp_gtk_image_get_pixbuf (env, obj));
317 }
318
319 /**
320  * Sets this to a scaled version of the original pixbuf
321  * width and height of the destination GtkImage must be set.
322  */
323 JNIEXPORT void JNICALL 
324 Java_gnu_java_awt_peer_gtk_GtkImage_createScaledPixbuf(JNIEnv *env, 
325                                                        jobject destination, 
326                                                        jobject source,
327                                                        jint hints)
328 {
329   GdkPixbuf* dst;
330   int width, height;
331   jclass cls;
332   jfieldID field;
333
334   GdkPixbuf *pixbuf;
335
336   cls = (*env)->GetObjectClass (env, destination);
337   field = (*env)->GetFieldID (env, cls, "width", "I");
338   g_assert (field != 0);
339   width = (*env)->GetIntField (env, destination, field);
340
341   field = (*env)->GetFieldID (env, cls, "height", "I");
342   g_assert (field != 0);
343   height = (*env)->GetIntField (env, destination, field);
344
345   pixbuf = cp_gtk_image_get_pixbuf (env, source);
346
347   dst = gdk_pixbuf_scale_simple(pixbuf,
348                                 width, height,
349                                 mapHints(hints));
350
351   createRawData (env, destination, (void *)dst);
352 }
353
354 /**
355  * Used by GtkFramePeer
356  */
357 GdkPixbuf *cp_gtk_image_get_pixbuf (JNIEnv *env, jobject obj)
358 {
359   jclass cls;
360   jfieldID data_fid;
361   jobject data;
362
363   cls = (*env)->GetObjectClass (env, obj);
364   data_fid = (*env)->GetFieldID (env, cls, "pixbuf", 
365                                  "Lgnu/classpath/Pointer;");
366   g_assert (data_fid != 0);
367   data = (*env)->GetObjectField (env, obj, data_fid);
368
369   if (data == NULL)
370     return NULL;
371
372   return (GdkPixbuf *)JCL_GetRawData (env, data);
373 }
374
375 /**
376  * Maps java.awt.Image scaling hints to the native GDK ones.
377  */
378 static GdkInterpType mapHints(jint hints)
379 {
380   switch ( hints ) 
381     {
382       /* For FAST, we use the nearest-neighbor. Fastest and lowest quality. */
383     case SCALE_FAST:
384     case SCALE_REPLICATE:
385       return GDK_INTERP_NEAREST;
386
387       /* Hyperbolic for smooth. Slowest too. */
388     case SCALE_SMOOTH:
389       return GDK_INTERP_HYPER;
390       
391       /* the inbetweenish method */
392     case SCALE_AREA_AVERAGING:
393       return GDK_INTERP_TILES;
394
395       /* default to bilinear */
396     }
397   return GDK_INTERP_BILINEAR;
398 }
399
400 /* Sets the width and height fields of a GtkImage object. */
401 static void setWidthHeight (JNIEnv * env, jobject obj, int width, int height)
402 {
403   jclass cls;
404   jfieldID field;
405   
406   cls = (*env)->GetObjectClass (env, obj);
407   g_assert (cls != 0);
408   field = (*env)->GetFieldID (env, cls, "width", "I");
409   g_assert (field != 0);
410   (*env)->SetIntField (env, obj, field, (jint)width);
411    
412   field = (*env)->GetFieldID (env, cls, "height", "I");
413   g_assert (field != 0);
414   (*env)->SetIntField (env, obj, field, (jint)height);
415 }
416
417 /* Store and get the pixbuf pointer */
418 static void
419 createRawData (JNIEnv * env, jobject obj, void *ptr)
420 {
421   jclass cls;
422   jobject data;
423   jfieldID data_fid;
424
425   cls = (*env)->GetObjectClass (env, obj);
426   data_fid = (*env)->GetFieldID (env, cls, "pixbuf", 
427                                  "Lgnu/classpath/Pointer;");
428   g_assert (data_fid != 0);
429
430   data = JCL_NewRawDataObject (env, ptr);
431
432   (*env)->SetObjectField (env, obj, data_fid, data);
433 }
434