2003/10/16 05:24:23
[org.ibex.core.git] / src / org / xwt / plat / GCJ.cc
index bba04f8..9a9b1bb 100644 (file)
@@ -21,8 +21,9 @@ extern "C" {
 #include <java/io/ByteArrayInputStream.h>
 #include <java/lang/RuntimeException.h>
 #include <org/xwt/plat/GCJ.h>
+#include <org/xwt/util/Log.h>
 
-
+using org::xwt::util::Log;
 
 // builtin.xwar /////////////////////////////////////////////////////////
 
@@ -39,102 +40,112 @@ java::io::InputStream* org::xwt::plat::GCJ::_getBuiltinInputStream() {
 
 // JPEG ////////////////////////////////////////////////////////////////
 
-#define INPUT_BUF_SIZE (1024 * 16)
-
 typedef struct {
     struct jpeg_source_mgr pub;
-    /* FIXME
-    org::xwt::plat::GCJ$JPEG* myself;
-    */
-} source_manager;
-
-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);
+    java::io::InputStream *is;
+    jbyteArray buf;
+} my_source_mgr_t;
+
+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) {
-  /* FIXME
-  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;
 }
 
 org::xwt::Picture* org::xwt::plat::GCJ::_decodeJPEG(java::io::InputStream* is, jstring name) {
     struct jpeg_decompress_struct cinfo;
+    my_error_mgr_t jerr;
+    my_source_mgr_t src;
     jintArray data;
     jint width;
     jint height;
-  
-    // 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;
     
-    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::log(&GCJ::class$,JvNewStringLatin1(msgbuf));
         jpeg_destroy_decompress(&cinfo);
-        throw t;
+        return 0;
     }
+  
+    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);
+    
+    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);
     jpeg_destroy_decompress(&cinfo);
+    
+    for(int i=0;i<data->length;i++)
+        elements(data)[i] |= 0xff000000; // alpha channel
+    
     return org::xwt::Platform::createPicture(data, width, height);
 }