#include <gcj/cni.h>
#include <gcj/array.h>
extern "C" {
+
+// hack for broken Solaris headers
+#define _WCHAR_T
+
#include <stdlib.h>
#include <stdio.h>
#include <setjmp.h>
#include "jpeglib.h"
}
+#include <org/xwt/Platform.h>
+#include <org/xwt/Picture.h>
#include <org/xwt/plat/GCJ.h>
#include <java/io/InputStream.h>
#include <java/io/ByteArrayInputStream.h>
#include <java/lang/RuntimeException.h>
#include <org/xwt/plat/GCJ.h>
-#include <org/xwt/plat/GCJ$JPEG.h>
+#include <org/xwt/util/Log.h>
+#ifdef TRUE
+#undef TRUE
+#endif
+#define TRUE 1
+using org::xwt::util::Log;
+// builtin.xwar /////////////////////////////////////////////////////////
+
+extern unsigned char builtin_bytes[];
+extern int builtin_length;
+
+java::io::InputStream* org::xwt::plat::GCJ::_getBuiltinInputStream() {
+ jbyteArray ret = JvNewByteArray(builtin_length);
+ memcpy(elements(ret), builtin_bytes, builtin_length);
+ return new java::io::ByteArrayInputStream(ret);
+}
-// JPEG ////////////////////////////////////////////////////////////////
-#define INPUT_BUF_SIZE (1024 * 16)
+
+// JPEG ////////////////////////////////////////////////////////////////
typedef struct {
struct jpeg_source_mgr pub;
- org::xwt::plat::GCJ$JPEG* myself;
-} source_manager;
+ java::io::InputStream *is;
+ jbyteArray buf;
+} my_source_mgr_t;
-void jpeg_error_handler (j_common_ptr cinfo) {
- jstring message = JvNewStringLatin1(cinfo->err->jpeg_message_table[cinfo->err->msg_code]);
- throw new java::lang::RuntimeException(message);
+typedef struct {
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+} my_error_mgr_t;
+
+static void error_exit (j_common_ptr cinfo) {
+ my_error_mgr_t *myerr = (my_error_mgr_t*) cinfo->err;
+ longjmp(myerr->setjmp_buffer,1);
}
-void term_source (j_decompress_ptr cinfo) { }
-void init_source (j_decompress_ptr cinfo) { }
+static void term_source (j_decompress_ptr cinfo) { }
+static void init_source (j_decompress_ptr cinfo) { }
boolean fill_input_buffer (j_decompress_ptr cinfo) {
- source_manager* src = (source_manager*)cinfo->src;
- jint nbytes = src->myself->is->read(src->myself->buffer, 0, INPUT_BUF_SIZE);
- if (nbytes <= 0) {
- // the JPEG library specifically suggests padding the end with EOF markers
- elements(src->myself->buffer)[0] = (jbyte)0xFF;
- elements(src->myself->buffer)[1] = (jbyte)JPEG_EOI;
- nbytes = 2;
- }
- src->pub.next_input_byte = (JOCTET*)elements(src->myself->buffer);
- src->pub.bytes_in_buffer = nbytes;
- return 1;
+ my_source_mgr_t* src = (my_source_mgr_t*) cinfo->src;
+ JOCTET *p = (JOCTET*)elements(src->buf);
+ jint n;
+ try {
+ n = src->is->read(src->buf, 0, src->buf->length);
+ } catch(java::lang::Throwable *e) {
+ n = -1;
+ }
+
+ src->pub.next_input_byte = p;
+
+ if (n <= 0) {
+ // the JPEG library specifically suggests padding the end with EOF markers
+ p[0] = 0xff;
+ p[1] = JPEG_EOI;
+ src->pub.bytes_in_buffer = 2;
+ } else {
+ src->pub.bytes_in_buffer = n;
+ }
+ return 1;
}
void skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
- source_manager* src = (source_manager*)cinfo->src;
- if (num_bytes > 0) {
- while (num_bytes > (long) src->pub.bytes_in_buffer) {
- num_bytes -= (long) src->pub.bytes_in_buffer;
- (void) fill_input_buffer(cinfo);
+ my_source_mgr_t* src = (my_source_mgr_t*) cinfo->src;
+
+ if (num_bytes <= 0) return;
+
+ while (num_bytes > src->pub.bytes_in_buffer) {
+ num_bytes -= src->pub.bytes_in_buffer;
+ fill_input_buffer(cinfo);
}
- src->pub.next_input_byte += (size_t) num_bytes;
- src->pub.bytes_in_buffer -= (size_t) num_bytes;
- }
+ src->pub.next_input_byte += num_bytes;
+ src->pub.bytes_in_buffer -= num_bytes;
}
-void org::xwt::plat::GCJ$JPEG::nativeDecompress() {
+void org::xwt::plat::GCJ::_decodeJPEG(java::io::InputStream* is, org::xwt::Picture* p) {
struct jpeg_decompress_struct cinfo;
-
- // set up our error handler
- struct jpeg_error_mgr error_handler;
- cinfo.err = jpeg_std_error(&error_handler);
- error_handler.error_exit = &jpeg_error_handler;
+ my_error_mgr_t jerr;
+ my_source_mgr_t src;
- jpeg_create_decompress(&cinfo);
- try {
- source_manager src;
- buffer = JvNewByteArray(INPUT_BUF_SIZE);
- src.pub.init_source = init_source;
- src.pub.fill_input_buffer = fill_input_buffer;
- src.pub.skip_input_data = skip_input_data;
- src.pub.resync_to_restart = jpeg_resync_to_restart;
- src.pub.term_source = term_source;
- src.myself = this;
- src.pub.next_input_byte = (JOCTET*)elements(buffer);
- src.pub.bytes_in_buffer = 0;
- cinfo.src = (jpeg_source_mgr*)&src;
-
- jpeg_read_header(&cinfo, 1);
- jpeg_start_decompress(&cinfo);
- width = cinfo.output_width;
- height = cinfo.output_height;
- data = JvNewIntArray(width * height);
-
- while (cinfo.output_scanline < cinfo.output_height) {
- JSAMPLE* dest = (JSAMPLE*)(elements(data) + cinfo.output_scanline * width);
- jpeg_read_scanlines(&cinfo, &dest, 1);
- }
-
- jpeg_finish_decompress(&cinfo);
-
- // fill in the alpha components
- for(int i=0; i<data->length; i++)
- elements(data)[i] |= (jint)0xff000000;
-
- } catch (java::lang::Throwable* t) {
+ src.is = is;
+ src.buf = JvNewByteArray(16384);
+
+ src.pub.init_source = init_source;
+ src.pub.fill_input_buffer = fill_input_buffer;
+ src.pub.skip_input_data = skip_input_data;
+ src.pub.resync_to_restart = jpeg_resync_to_restart;
+ src.pub.term_source = term_source;
+ src.pub.next_input_byte = NULL;
+ src.pub.bytes_in_buffer = 0;
+
+ if (setjmp(jerr.setjmp_buffer)) {
+ // FEATURE - we should handle errors better than this
+ char msgbuf[JMSG_LENGTH_MAX];
+ (jerr.pub.format_message)((j_common_ptr)&cinfo, msgbuf);
+ Log::info(&GCJ::class$,JvNewStringLatin1(msgbuf));
jpeg_destroy_decompress(&cinfo);
- throw t;
+ return;
}
+
+ jpeg_create_decompress(&cinfo);
+
+ cinfo.src = &src.pub;
+ cinfo.err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = error_exit;
+
+ jpeg_read_header(&cinfo,TRUE);
+ jpeg_start_decompress(&cinfo);
+
+ p->width = cinfo.output_width;
+ p->height = cinfo.output_height;
+ p->data = JvNewIntArray(p->width * p->height);
+
+ while (cinfo.output_scanline < cinfo.output_height) {
+ JSAMPLE *dest = (JSAMPLE*) (elements(p->data) + cinfo.output_scanline * p->width);
+ jpeg_read_scanlines(&cinfo,&dest,1);
+ }
+ jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
+
+ for(int i=0;i<p->data->length;i++)
+ elements(p->data)[i] |= 0xff000000; // alpha channel
}
// C++ new/delete operators (JvMalloc never fails)