2003/04/10 01:41:43
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:58:32 +0000 (06:58 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:58:32 +0000 (06:58 +0000)
darcs-hash:20040130065832-2ba56-9d2640f61c287a4e798572f5b3e075fe1e18bd2f.gz

src/org/ijg/jmorecfg.h.patch [new file with mode: 0644]
src/org/xwt/Box.java
src/org/xwt/Platform.java
src/org/xwt/Resources.java
src/org/xwt/plat/AWT.java
src/org/xwt/plat/GCJ.cc
src/org/xwt/plat/GCJ.java
src/org/xwt/plat/Win32.cc

diff --git a/src/org/ijg/jmorecfg.h.patch b/src/org/ijg/jmorecfg.h.patch
new file mode 100644 (file)
index 0000000..b703dda
--- /dev/null
@@ -0,0 +1,11 @@
+--- jmorecfg.h-        Tue Apr  8 04:33:05 2003
++++ jmorecfg.h Tue Apr  8 04:33:13 2003
+@@ -314,7 +314,7 @@
+ #define RGB_RED               0       /* Offset of Red in an RGB scanline element */
+ #define RGB_GREEN     1       /* Offset of Green */
+ #define RGB_BLUE      2       /* Offset of Blue */
+-#define RGB_PIXELSIZE 3       /* JSAMPLEs per RGB scanline element */
++#define RGB_PIXELSIZE 4       /* JSAMPLEs per RGB scanline element */
+ /* Definitions for speed-related optimizations. */
index 4cefc9e..caa7c8a 100644 (file)
@@ -408,13 +408,14 @@ public final class Box extends JSObject {
 
     /** loads the image described by string str, possibly blocking for a network load */
     static ImageDecoder getImage(String str, final Function callback) {
-        boolean ispng = false;
 
         if (str.indexOf(':') == -1) {
             String s = str;
             byte[] b = Resources.getResource(Resources.resolve(s + ".png", null));
-            if (b == null) return null;
-            return PNG.decode(new ByteArrayInputStream(b), str);
+           if (b != null) return PNG.decode(new ByteArrayInputStream(b), str);
+            b = Resources.getResource(Resources.resolve(s + ".jpeg", null));
+           if (b != null) return Platform.decodeJPEG(new ByteArrayInputStream(b), str);
+           return null;
             
         } else {
             Thread thread = Thread.currentThread();
@@ -427,10 +428,6 @@ public final class Box extends JSObject {
             mythread.setPriority(Thread.MIN_PRIORITY);
             mythread.done.release();
             try {
-                // FIXME use mime types here, not extensions
-                if (str.endsWith(".jpeg") || str.endsWith(".jpg"))
-                    str = "http://xmlrpc.xwt.org/jpeg2png/" + str.substring(str.indexOf("//") + 2);
-
                 HTTP http = new HTTP(str);
                 final HTTP.HTTPInputStream in = http.GET();
                 final int contentLength = in.getContentLength();
@@ -461,9 +458,10 @@ public final class Box extends JSObject {
                             return ret;
                         }
                     };
-                
+
                 if (str.endsWith(".gif")) return GIF.decode(is, str);
-                else return PNG.decode(is, str);
+                else if (str.endsWith(".jpeg") || str.endsWith(".jpg")) return Platform.decodeJPEG(is, str);
+               else return PNG.decode(is, str);
 
             } catch (IOException e) {
                 if (Log.on) Log.log(Box.class, "error while trying to load an image from " + str);
@@ -504,7 +502,7 @@ public final class Box extends JSObject {
                 if (Log.on) Log.log(Box.class, "unable to load image " + s + " at " +
                                     Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine);
                 return;
-            }
+           }
             if (sizetoimage) syncSizeToImage();
             dirty();
         }
index 1b6056a..80076d3 100644 (file)
@@ -241,6 +241,10 @@ public class Platform {
         return null;
     }
 
+    /** convert a JPEG into an Image */
+    protected ImageDecoder _decodeJPEG(InputStream is, String name) { return null; }
+
+
     // Static methods -- thunk to the instance /////////////////////////////////////////////////////////////////////////
 
     /** if true, org.xwt.Surface should generate Click messages automatically when a Release happens after a Press and the mouse has not moved much */
@@ -401,6 +405,10 @@ public class Platform {
         return cachedProxyInfo;
     }
 
+    public static synchronized ImageDecoder decodeJPEG(InputStream is, String name) {
+       return platform._decodeJPEG(is, name);
+    }
+
     // Helpful font parsing stuff //////////////////////////////////////////////////////
 
     public static class ParsedFont {
index 1996501..59884c9 100644 (file)
@@ -39,9 +39,8 @@ public class Resources {
             char c = name.charAt(i);
             if (!((c >= 'A' && c <= 'Z') ||
                   (c >= 'a' && c <= 'z') ||
-                  c == '_' ||
-                  (c >= '0' && c <= '9') ||
-                  (c == '.' && i == name.length() - 4))) return false;
+                  c == '_' || c == '.' || 
+                  (c >= '0' && c <= '9'))) return false;
         }
         return true;
     }
index 7005f1e..81edee0 100644 (file)
@@ -127,12 +127,12 @@ public class AWT extends Platform {
 
         int[] data = null;
         public Image i = null;
-        private static MediaTracker mediatracker = new MediaTracker(new Canvas());
         private static ColorModel cmodel = new DirectColorModel(32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
         
         public AWTPicture(int[] b, int w, int h) {
             data = b;
             Image img = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(w, h, cmodel, b, 0, w));
+           MediaTracker mediatracker = new MediaTracker(new Canvas());
             mediatracker.addImage(img, 1);
             try { mediatracker.waitForAll(); } catch (InterruptedException e) { }
             mediatracker.removeImage(img);
@@ -411,6 +411,34 @@ public class AWT extends Platform {
         }
     }
 
+    protected ImageDecoder _decodeJPEG(InputStream is, String name) {
+       try {
+           Image i = Toolkit.getDefaultToolkit().createImage(org.xwt.Resources.isToByteArray(is));
+           MediaTracker mediatracker = new MediaTracker(new Canvas());
+            mediatracker.addImage(i, 1);
+           try { mediatracker.waitForAll(); } catch (InterruptedException e) { }
+           mediatracker.removeImage(i);
+           final int width = i.getWidth(null);
+           final int height = i.getHeight(null);
+           final int[] data = new int[width * height];
+           PixelGrabber pg = new PixelGrabber(i, 0, 0, width, height, data, 0, width);
+           pg.grabPixels();
+           if ((pg.getStatus() & ImageObserver.ABORT) != 0) {
+               Log.log(this, "PixelGrabber reported an error while decoding JPEG image " + name);
+               return null;
+           }
+           return new ImageDecoder() {
+                   public int getWidth() { return width; }
+                   public int getHeight() { return height; }
+                   public int[] getData() { return data; }
+               };
+       } catch (Exception e) {
+           Log.log(this, "Exception caught while decoding JPEG image " + name);
+           Log.log(this, e);
+           return null;
+       }
+    }
+
     // Font Handling Stuff //////////////////////////////////////////////////////////
 
     protected String[] _listFonts() { return fontList; }
index ff2f84d..b35c94f 100644 (file)
@@ -1 +1,100 @@
-           
+#include <stdlib.h>
+#include <stdio.h>
+#include <gcj/cni.h>
+#include <gcj/array.h>
+#include "jpeglib.h"
+#include <setjmp.h>
+
+#include <java/lang/RuntimeException.h>
+#include <java/io/InputStream.h>
+#include <org/xwt/plat/GCJ.h>
+#include <org/xwt/plat/GCJ$JPEG.h>
+
+#define INPUT_BUF_SIZE (1024 * 16)
+
+typedef struct {
+    struct jpeg_source_mgr pub;
+    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);
+}
+
+void term_source (j_decompress_ptr cinfo) { }
+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;
+}
+
+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);
+    }
+    src->pub.next_input_byte += (size_t) num_bytes;
+    src->pub.bytes_in_buffer -= (size_t) num_bytes;
+  }
+}
+
+void org::xwt::plat::GCJ$JPEG::nativeDecompress() {
+    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;
+    
+    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) {
+        jpeg_destroy_decompress(&cinfo);
+        throw t;
+    }
+    jpeg_destroy_decompress(&cinfo);
+}
+
+
index 34c89ea..4a6d23f 100644 (file)
@@ -2,6 +2,8 @@
 package org.xwt.plat;
 
 import org.xwt.*;
+import org.xwt.util.*;
+import java.io.*;
 
 /** common superclass for all platforms that use GCJ to compile a native binary */
 public abstract class GCJ extends Platform {
@@ -20,5 +22,30 @@ public abstract class GCJ extends Platform {
         public Java2Weak(Object o) { super(o); }
     }
         
+    // FIXME
+    protected ImageDecoder _decodeJPEG(InputStream is, String name) {
+       try {
+           return new JPEG(is);
+       } catch (Exception e) {
+           Log.log(this, "Exception while decoding JPEG image " + name);
+           Log.log(this, e);
+           return null;
+       }
+    }
+
+    /** Converts an InputStream carrying a JPEG image into an ARGB int[] */
+    private static class JPEG implements ImageDecoder {
+       int[] data;
+       byte[] buffer;
+       int width, height;
+       InputStream is;
+       
+       public final int[] getData() { return data; }
+       public final int getWidth() { return width; }
+       public final int getHeight() { return height; }
+       private JPEG(InputStream is) { this.is = is; nativeDecompress(); buffer = null; }
+       private native void nativeDecompress();
+    }
+
 }
 
index 240b39a..6ba10bf 100644 (file)
@@ -1,4 +1,8 @@
 // Copyright 2002 Adam Megacz, see the COPYING file for licensing [LGPL]
+#include "GCJ.cc"
+
+// we have to do this because the jpeg libraries use the symbol 'INT32'
+#define INT32 WIN32_INT32
 
 // this has to precede the others so we don't get collisions on min/max
 #include <org/xwt/Box.h>
@@ -37,8 +41,6 @@
 #include <java/lang/System.h>
 #include <java/io/PrintStream.h>
 
-#include "GCJ.cc"
-
 #define WM_USER_SETCURSOR WM_USER
 #define WM_USER_DISPOSE (WM_USER + 1)
 #define WM_USER_CREATEWINDOW (WM_USER + 2)