2003/10/17 06:09:38
[org.ibex.core.git] / src / org / xwt / plat / GCJ.cc
1 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
2
3 // Inclusions /////////////////////////////////////////////////////////
4
5 #include <gcj/cni.h>
6 #include <gcj/array.h>
7 extern "C" {
8
9 // hack for broken Solaris headers
10 #define _WCHAR_T
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <setjmp.h>
15 #include "jpeglib.h"
16 }
17 #include <org/xwt/Platform.h>
18 #include <org/xwt/Picture.h>
19 #include <org/xwt/plat/GCJ.h>
20 #include <java/io/InputStream.h>
21 #include <java/io/ByteArrayInputStream.h>
22 #include <java/lang/RuntimeException.h>
23 #include <org/xwt/plat/GCJ.h>
24 #include <org/xwt/util/Log.h>
25
26 using org::xwt::util::Log;
27
28 #define TRUE 1
29
30 // builtin.xwar /////////////////////////////////////////////////////////
31
32 extern unsigned char builtin_bytes[];
33 extern int builtin_length;
34
35 java::io::InputStream* org::xwt::plat::GCJ::_getBuiltinInputStream() {
36     jbyteArray ret = JvNewByteArray(builtin_length);
37     memcpy(elements(ret), builtin_bytes, builtin_length);
38     return new java::io::ByteArrayInputStream(ret);
39 }
40
41
42
43 // JPEG ////////////////////////////////////////////////////////////////
44
45 typedef struct {
46     struct jpeg_source_mgr pub;
47     java::io::InputStream *is;
48     jbyteArray buf;
49 } my_source_mgr_t;
50
51 typedef struct {
52     struct jpeg_error_mgr pub;
53     jmp_buf setjmp_buffer;
54 } my_error_mgr_t;
55
56 static void error_exit (j_common_ptr cinfo) {
57     my_error_mgr_t *myerr = (my_error_mgr_t*) cinfo->err;
58     longjmp(myerr->setjmp_buffer,1);
59 }
60
61 static void term_source (j_decompress_ptr cinfo) { }
62 static void init_source (j_decompress_ptr cinfo) { }
63
64 boolean fill_input_buffer (j_decompress_ptr cinfo) {
65     my_source_mgr_t* src = (my_source_mgr_t*) cinfo->src;
66     JOCTET *p = (JOCTET*)elements(src->buf);
67     jint n;
68     try {
69         n = src->is->read(src->buf, 0, src->buf->length);
70     } catch(java::lang::Throwable *e) {
71         n = -1;
72     }
73     
74     src->pub.next_input_byte = p;
75     
76     if (n <= 0) {
77         // the JPEG library specifically suggests padding the end with EOF markers
78         p[0] = 0xff;
79         p[1] = JPEG_EOI;
80         src->pub.bytes_in_buffer = 2;
81     } else {
82         src->pub.bytes_in_buffer = n;
83     }
84     return 1;
85 }
86
87 void skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
88     my_source_mgr_t* src = (my_source_mgr_t*) cinfo->src;
89     
90     if (num_bytes <= 0) return; 
91     
92     while (num_bytes > src->pub.bytes_in_buffer) {
93         num_bytes -= src->pub.bytes_in_buffer;
94         fill_input_buffer(cinfo);
95     }
96     src->pub.next_input_byte += num_bytes;
97     src->pub.bytes_in_buffer -= num_bytes;
98 }
99
100 org::xwt::Picture* org::xwt::plat::GCJ::_decodeJPEG(java::io::InputStream* is, jstring name) {
101     struct jpeg_decompress_struct cinfo;
102     my_error_mgr_t jerr;
103     my_source_mgr_t src;
104     jintArray data;
105     jint width;
106     jint height;
107     
108     src.is = is;
109     src.buf = JvNewByteArray(16384);
110     
111     src.pub.init_source = init_source;
112     src.pub.fill_input_buffer = fill_input_buffer;
113     src.pub.skip_input_data = skip_input_data;
114     src.pub.resync_to_restart = jpeg_resync_to_restart;
115     src.pub.term_source = term_source;
116     src.pub.next_input_byte = NULL;
117     src.pub.bytes_in_buffer = 0;
118     
119     if (setjmp(jerr.setjmp_buffer)) {
120         // FEATURE - we should handle errors better than this
121         char msgbuf[JMSG_LENGTH_MAX];
122         (jerr.pub.format_message)((j_common_ptr)&cinfo, msgbuf);
123         Log::log(&GCJ::class$,JvNewStringLatin1(msgbuf));
124         jpeg_destroy_decompress(&cinfo);
125         return 0;
126     }
127   
128     jpeg_create_decompress(&cinfo);
129     
130     cinfo.src = &src.pub;
131     cinfo.err = jpeg_std_error(&jerr.pub);
132     jerr.pub.error_exit = error_exit;
133     
134     jpeg_read_header(&cinfo,TRUE);
135     jpeg_start_decompress(&cinfo);
136     
137     width = cinfo.output_width;
138     height = cinfo.output_height;
139     data = JvNewIntArray(width * height);
140     
141     while (cinfo.output_scanline < cinfo.output_height) {
142         JSAMPLE *dest = (JSAMPLE*) (elements(data) + cinfo.output_scanline * width);
143         jpeg_read_scanlines(&cinfo,&dest,1);
144     }
145     jpeg_finish_decompress(&cinfo);
146     jpeg_destroy_decompress(&cinfo);
147     
148     for(int i=0;i<data->length;i++)
149         elements(data)[i] |= 0xff000000; // alpha channel
150     
151     return org::xwt::Platform::createPicture(data, width, height);
152 }
153
154 // C++ new/delete operators (JvMalloc never fails)
155 void* operator new(size_t size) { return JvMalloc(size); }
156 void* operator new[](size_t size) { return JvMalloc(size);}
157 void operator delete(void *p) { JvFree(p); }
158 void operator delete[](void *p) { JvFree(p); }