From 4f7f0b92b26b48cd88f534c5ca29b5bce98929b2 Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 06:58:32 +0000 Subject: [PATCH] 2003/04/10 01:41:43 darcs-hash:20040130065832-2ba56-9d2640f61c287a4e798572f5b3e075fe1e18bd2f.gz --- src/org/ijg/jmorecfg.h.patch | 11 +++++ src/org/xwt/Box.java | 18 ++++---- src/org/xwt/Platform.java | 8 ++++ src/org/xwt/Resources.java | 5 +-- src/org/xwt/plat/AWT.java | 30 ++++++++++++- src/org/xwt/plat/GCJ.cc | 101 +++++++++++++++++++++++++++++++++++++++++- src/org/xwt/plat/GCJ.java | 27 +++++++++++ src/org/xwt/plat/Win32.cc | 6 ++- 8 files changed, 189 insertions(+), 17 deletions(-) create mode 100644 src/org/ijg/jmorecfg.h.patch diff --git a/src/org/ijg/jmorecfg.h.patch b/src/org/ijg/jmorecfg.h.patch new file mode 100644 index 0000000..b703dda --- /dev/null +++ b/src/org/ijg/jmorecfg.h.patch @@ -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. */ diff --git a/src/org/xwt/Box.java b/src/org/xwt/Box.java index 4cefc9e..caa7c8a 100644 --- a/src/org/xwt/Box.java +++ b/src/org/xwt/Box.java @@ -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(); } diff --git a/src/org/xwt/Platform.java b/src/org/xwt/Platform.java index 1b6056a..80076d3 100644 --- a/src/org/xwt/Platform.java +++ b/src/org/xwt/Platform.java @@ -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 { diff --git a/src/org/xwt/Resources.java b/src/org/xwt/Resources.java index 1996501..59884c9 100644 --- a/src/org/xwt/Resources.java +++ b/src/org/xwt/Resources.java @@ -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; } diff --git a/src/org/xwt/plat/AWT.java b/src/org/xwt/plat/AWT.java index 7005f1e..81edee0 100644 --- a/src/org/xwt/plat/AWT.java +++ b/src/org/xwt/plat/AWT.java @@ -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; } diff --git a/src/org/xwt/plat/GCJ.cc b/src/org/xwt/plat/GCJ.cc index ff2f84d..b35c94f 100644 --- a/src/org/xwt/plat/GCJ.cc +++ b/src/org/xwt/plat/GCJ.cc @@ -1 +1,100 @@ - +#include +#include +#include +#include +#include "jpeglib.h" +#include + +#include +#include +#include +#include + +#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; ilength; i++) + elements(data)[i] |= (jint)0xff000000; + + } catch (java::lang::Throwable* t) { + jpeg_destroy_decompress(&cinfo); + throw t; + } + jpeg_destroy_decompress(&cinfo); +} + + diff --git a/src/org/xwt/plat/GCJ.java b/src/org/xwt/plat/GCJ.java index 34c89ea..4a6d23f 100644 --- a/src/org/xwt/plat/GCJ.java +++ b/src/org/xwt/plat/GCJ.java @@ -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(); + } + } diff --git a/src/org/xwt/plat/Win32.cc b/src/org/xwt/plat/Win32.cc index 240b39a..6ba10bf 100644 --- a/src/org/xwt/plat/Win32.cc +++ b/src/org/xwt/plat/Win32.cc @@ -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 @@ -37,8 +41,6 @@ #include #include -#include "GCJ.cc" - #define WM_USER_SETCURSOR WM_USER #define WM_USER_DISPOSE (WM_USER + 1) #define WM_USER_CREATEWINDOW (WM_USER + 2) -- 1.7.10.4