OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [native/] [jni/] [gtk-peer/] [gnu_java_awt_peer_gtk_GdkPixbufDecoder.c] - Blame information for rev 774

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 774 jeremybenn
/* gdkpixbufdecoder.c
2
   Copyright (C) 1999, 2003, 2004, 2005, 2006 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 <gtkpeer.h>
39
#include <gdk/gdk.h>
40
#include <gdk-pixbuf/gdk-pixbuf.h>
41
#include <gdk-pixbuf/gdk-pixbuf-loader.h>
42
 
43
#include <jni.h>
44
#include <jcl.h>
45
#include "gnu_java_awt_peer_gtk_GdkPixbufDecoder.h"
46
 
47
#include <string.h>
48
#include <stdlib.h>
49
 
50
/* Union used for type punning. */
51
union env_union
52
{
53
  void **void_env;
54
  JNIEnv **jni_env;
55
};
56
 
57
static JavaVM *vm;
58
 
59
static jmethodID areaPreparedID;
60
static jmethodID areaUpdatedID;
61
static jmethodID dataOutputWriteID;
62
static jmethodID registerFormatID;
63
 
64
static void
65
area_prepared_cb (GdkPixbufLoader *loader,
66
               jobject *decoder)
67
{
68
  JNIEnv *env = NULL;
69
  union env_union e;
70
  jint width = 0;
71
  jint height = 0;
72
  GdkPixbuf *pixbuf = NULL;
73
 
74
  pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
75
  g_assert (pixbuf != NULL);
76
 
77
  width = gdk_pixbuf_get_width (pixbuf);
78
  height = gdk_pixbuf_get_height (pixbuf);
79
 
80
  g_assert (decoder != NULL);
81
 
82
  e.jni_env = &env;
83
  (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
84
 
85
  (*env)->CallVoidMethod (env,
86
                          *decoder,
87
                          areaPreparedID,
88
                          width, height);
89
}
90
 
91
static void
92
area_updated_cb (GdkPixbufLoader *loader,
93
              gint x, gint y,
94
              gint width, gint height,
95
              jobject *decoder)
96
{
97
  JNIEnv *env;
98
  union env_union e;
99
  jint stride_bytes, stride_pixels, n_channels, n_pixels;
100
  jintArray jpixels;
101
  jint *java_pixels;
102
  guchar *gdk_pixels;
103
 
104
  GdkPixbuf *pixbuf_no_alpha = NULL;
105
  GdkPixbuf *pixbuf = NULL;
106
 
107
#ifndef WORDS_BIGENDIAN
108
  int i;
109
#endif
110
 
111
  pixbuf_no_alpha = gdk_pixbuf_loader_get_pixbuf (loader);
112
  if (pixbuf_no_alpha == NULL)
113
    return;
114
 
115
  pixbuf = gdk_pixbuf_add_alpha(pixbuf_no_alpha, FALSE, 0, 0, 0);
116
  g_assert (gdk_pixbuf_get_has_alpha (pixbuf));
117
 
118
  stride_bytes = gdk_pixbuf_get_rowstride (pixbuf);
119
  n_channels = gdk_pixbuf_get_n_channels (pixbuf);
120
  stride_pixels =  stride_bytes / n_channels;
121
  n_pixels = height * stride_pixels;
122
  gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
123
 
124
  e.jni_env = &env;
125
  (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
126
 
127
  jpixels = (*env)->NewIntArray (env, n_pixels);
128
 
129
  java_pixels = (*env)->GetIntArrayElements (env, jpixels, NULL);
130
 
131
  memcpy (java_pixels,
132
          gdk_pixels + (y * stride_bytes),
133
          (height * stride_bytes));
134
 
135
#ifndef WORDS_BIGENDIAN
136
  /* convert pixels from 0xBBGGRRAA to 0xAARRGGBB */
137
  for (i = 0; i < n_pixels; ++i)
138
    {
139
      java_pixels[i] = SWAPU32 ((unsigned)java_pixels[i]);
140
    }
141
#endif
142
 
143
  g_object_unref (pixbuf);
144
 
145
  (*env)->ReleaseIntArrayElements (env, jpixels, java_pixels, 0);
146
 
147
  (*env)->CallVoidMethod (env,
148
                          *decoder,
149
                          areaUpdatedID,
150
                          (jint) x, (jint) y,
151
                          (jint) width, (jint) height,
152
                          jpixels,
153
                          stride_pixels);
154
 
155
  (*env)->DeleteLocalRef(env, jpixels);
156
}
157
 
158
static void
159
closed_cb (GdkPixbufLoader *loader __attribute__((unused)), jobject *decoder)
160
{
161
  JNIEnv *env;
162
  union env_union e;
163
  e.jni_env = &env;
164
  (*vm)->GetEnv (vm, e.void_env, JNI_VERSION_1_1);
165
 
166
  (*env)->DeleteGlobalRef (env, *decoder);
167
  g_free (decoder);
168
}
169
 
170
 
171
 
172
JNIEXPORT void JNICALL
173
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initState
174
  (JNIEnv *env, jobject obj)
175
{
176
  GdkPixbufLoader *loader = NULL;
177
  jobject *decoder = NULL;
178
 
179
  decoder = (jobject *) g_malloc (sizeof (jobject));
180
  g_assert (decoder != NULL);
181
  *decoder = (*env)->NewGlobalRef (env, obj);
182
 
183
  loader = gdk_pixbuf_loader_new ();
184
  g_assert (loader != NULL);
185
  g_signal_connect (loader, "area-prepared", G_CALLBACK (area_prepared_cb), decoder);
186
  g_signal_connect (loader, "area-updated", G_CALLBACK (area_updated_cb), decoder);
187
  g_signal_connect (loader, "closed", G_CALLBACK (closed_cb), decoder);
188
 
189
  gtkpeer_set_pixbuf_loader (env, obj, loader);
190
}
191
 
192
static void
193
query_formats (JNIEnv *env, jclass clazz)
194
{
195
  jobject jformat;
196
  GSList *formats, *f;
197
  GdkPixbufFormat *format;
198
  gchar **ch, *name;
199
  gint count;
200
 
201
  jclass formatClass;
202
  jmethodID addExtensionID;
203
  jmethodID addMimeTypeID;
204
  jobject string;
205
 
206
  formatClass = (*env)->FindClass
207
    (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec");
208
 
209
  g_assert(formatClass != NULL);
210
 
211
  addExtensionID = (*env)->GetMethodID (env, formatClass,
212
                                        "addExtension",
213
                                        "(Ljava/lang/String;)V");
214
 
215
  addMimeTypeID = (*env)->GetMethodID (env, formatClass,
216
                                       "addMimeType",
217
                                       "(Ljava/lang/String;)V");
218
 
219
  formats = gdk_pixbuf_get_formats ();
220
 
221
  for (f = formats; f; f = f->next)
222
    {
223
      format = (GdkPixbufFormat *) f->data;
224
      name = gdk_pixbuf_format_get_name(format);
225
 
226
      string = (*env)->NewStringUTF(env, name);
227
      g_assert(string != NULL);
228
 
229
      jformat = (*env)->CallStaticObjectMethod
230
        (env, clazz, registerFormatID, string,
231
         (jboolean) gdk_pixbuf_format_is_writable(format));
232
      (*env)->DeleteLocalRef(env, string);
233
      g_free(name);
234
 
235
      g_assert(jformat != NULL);
236
 
237
      ch = gdk_pixbuf_format_get_extensions(format);
238
      count = 0;
239
      while (*ch)
240
        {
241
          string = (*env)->NewStringUTF(env, *ch);
242
          g_assert(string != NULL);
243
          (*env)->CallVoidMethod (env, jformat, addExtensionID, string);
244
          (*env)->DeleteLocalRef(env, string);
245
          ++ch;
246
          ++count;
247
        }
248
      g_strfreev(ch - count);
249
 
250
      ch = gdk_pixbuf_format_get_mime_types(format);
251
      count = 0;
252
      while (*ch)
253
        {
254
          string = (*env)->NewStringUTF(env, *ch);
255
          g_assert(string != NULL);
256
          (*env)->CallVoidMethod (env, jformat, addMimeTypeID, string);
257
          (*env)->DeleteLocalRef(env, string);
258
          ++ch;
259
          ++count;
260
        }
261
      g_strfreev(ch - count);
262
      (*env)->DeleteLocalRef(env, jformat);
263
    }
264
 
265
  g_slist_free(formats);
266
}
267
 
268
 
269
JNIEXPORT void JNICALL
270
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_initStaticState
271
  (JNIEnv *env, jclass clazz)
272
{
273
  jclass writerClass;
274
 
275
  (*env)->GetJavaVM(env, &vm);
276
 
277
  areaPreparedID = (*env)->GetMethodID (env, clazz,
278
                                        "areaPrepared",
279
                                        "(II)V");
280
 
281
  areaUpdatedID = (*env)->GetMethodID (env, clazz,
282
                                       "areaUpdated",
283
                                       "(IIII[II)V");
284
 
285
  registerFormatID = (*env)->GetStaticMethodID
286
    (env, clazz,
287
     "registerFormat",
288
     "(Ljava/lang/String;Z)"
289
     "Lgnu/java/awt/peer/gtk/GdkPixbufDecoder$ImageFormatSpec;");
290
 
291
  writerClass = (*env)->FindClass
292
    (env, "gnu/java/awt/peer/gtk/GdkPixbufDecoder$GdkPixbufWriter");
293
  dataOutputWriteID = (*env)->GetMethodID (env, writerClass,
294
                                             "write", "([B)V");
295
 
296
  query_formats (env, clazz);
297
 
298
  gtkpeer_init_pixbuf_IDs (env);
299
}
300
 
301
 
302
JNIEXPORT void JNICALL
303
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_finish
304
(JNIEnv *env, jobject obj, jboolean needs_close)
305
{
306
  GdkPixbufLoader *loader = NULL;
307
 
308
  loader = (GdkPixbufLoader *) gtkpeer_get_pixbuf_loader(env, obj);
309
  if (loader == NULL)
310
    return;
311
 
312
  if (needs_close)
313
    gdk_pixbuf_loader_close (loader, NULL);
314
  g_object_unref (loader);
315
}
316
 
317
JNIEXPORT void JNICALL
318
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpDone
319
(JNIEnv *env, jobject obj)
320
{
321
  GError *err = NULL;
322
  GdkPixbufLoader *loader = NULL;
323
 
324
  loader = (GdkPixbufLoader *) gtkpeer_get_pixbuf_loader (env, obj);
325
  g_assert (loader != NULL);
326
 
327
  gdk_pixbuf_loader_close (loader, &err);
328
 
329
  if (err != NULL)
330
    {
331
      JCL_ThrowException (env, "java/io/IOException", err->message);
332
      g_error_free (err);
333
    }
334
}
335
 
336
struct stream_save_request
337
{
338
  JNIEnv *env;
339
  jobject *writer;
340
};
341
 
342
static gboolean
343
save_to_stream(const gchar *buf,
344
               gsize count,
345
               GError **error __attribute__((unused)),
346
               gpointer data)
347
{
348
  struct stream_save_request *ssr = (struct stream_save_request *)data;
349
 
350
  jbyteArray jbuf;
351
  jbyte *cbuf;
352
 
353
  jbuf = (*(ssr->env))->NewByteArray ((ssr->env), count);
354
  cbuf = (*(ssr->env))->GetByteArrayElements ((ssr->env), jbuf, NULL);
355
  memcpy (cbuf, buf, count);
356
  (*(ssr->env))->ReleaseByteArrayElements ((ssr->env), jbuf, cbuf, 0);
357
  (*(ssr->env))->CallVoidMethod ((ssr->env), *(ssr->writer),
358
                                 dataOutputWriteID, jbuf);
359
  (*(ssr->env))->DeleteLocalRef((ssr->env), jbuf);
360
 
361
  return TRUE;
362
}
363
 
364
 
365
JNIEXPORT void JNICALL
366
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_streamImage
367
(JNIEnv *env, jclass clazz __attribute__((unused)),
368
 jintArray jarr, jstring jenctype, jint width, jint height,
369
 jboolean hasAlpha, jobject writer)
370
{
371
  GdkPixbuf* pixbuf;
372
  jint *ints;
373
  guchar a, r, g, b, *pix, *p;
374
  GError *err = NULL;
375
  const char *enctype;
376
  int i;
377
  struct stream_save_request ssr;
378
 
379
  ssr.writer = &writer;
380
  ssr.env = env;
381
 
382
  ints = (*env)->GetIntArrayElements (env, jarr, NULL);
383
  pix = g_malloc(width * height * (hasAlpha ? 4 : 3));
384
 
385
  enctype = (*env)->GetStringUTFChars (env, jenctype, NULL);
386
  g_assert(enctype != NULL);
387
 
388
  g_assert (pix != NULL);
389
  g_assert (ints != NULL);
390
 
391
  p = pix;
392
  for (i = 0; i < width*height; ++i)
393
    {
394
      /*
395
       * Java encodes pixels as integers in a predictable arithmetic order:
396
       * 0xAARRGGBB. Since these are jints, JNI has already byte-swapped
397
       * them for us if necessary, so they're in "our" endianness, whatever
398
       * that is. It uses 4 bytes per pixel whether or not there's an alpha
399
       * channel.
400
       */
401
 
402
      a = 0xff & (ints[i] >> 24);
403
      r = 0xff & (ints[i] >> 16);
404
      g = 0xff & (ints[i] >> 8);
405
      b = 0xff & ints[i];
406
 
407
      /*
408
       * GDK-pixbuf has a very different storage model:
409
       *
410
       *  - A different alpha order (alpha after colors).
411
       *  - A different packing model (no alpha -> 3-bytes-per-pixel).
412
       *  - A different "RGB" order (host memory order, not endian-neutral).
413
       */
414
 
415
      *p++ = r;
416
      *p++ = g;
417
      *p++ = b;
418
      if (hasAlpha)
419
        *p++ = a;
420
    }
421
 
422
  pixbuf =  gdk_pixbuf_new_from_data (pix,
423
                                      GDK_COLORSPACE_RGB,
424
                                      (gboolean) hasAlpha,
425
                                      8, width, height,
426
                                      width * (hasAlpha ? 4 : 3), /* rowstride */
427
                                      NULL, NULL);
428
  g_assert (pixbuf != NULL);
429
 
430
  g_assert(gdk_pixbuf_save_to_callback (pixbuf,
431
                                        &save_to_stream,
432
                                        &ssr,
433
                                        enctype,
434
                                        &err, NULL));
435
 
436
  g_object_unref (pixbuf);
437
 
438
  g_free(pix);
439
 
440
  (*env)->ReleaseStringUTFChars (env, jenctype, enctype);
441
  (*env)->ReleaseIntArrayElements (env, jarr, ints, 0);
442
}
443
 
444
 
445
JNIEXPORT void JNICALL
446
Java_gnu_java_awt_peer_gtk_GdkPixbufDecoder_pumpBytes
447
  (JNIEnv *env, jobject obj, jbyteArray jarr, jint len)
448
{
449
  GdkPixbufLoader *loader = NULL;
450
  jbyte *bytes = NULL;
451
  GError *err = NULL;
452
 
453
  g_assert (len >= 1);
454
  g_assert (jarr != NULL);
455
 
456
  bytes = (*env)->GetByteArrayElements (env, jarr, NULL);
457
  g_assert (bytes != NULL);
458
  loader = (GdkPixbufLoader *) gtkpeer_get_pixbuf_loader (env, obj);
459
  g_assert (loader != NULL);
460
 
461
  gdk_pixbuf_loader_write (loader, (const guchar *) bytes, len, &err);
462
 
463
  (*env)->ReleaseByteArrayElements (env, jarr, bytes, 0);
464
 
465
  if (err != NULL)
466
    {
467
      JCL_ThrowException (env, "java/io/IOException", err->message);
468
      g_error_free (err);
469
    }
470
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.