--- /dev/null
+--- 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. */
/** 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();
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();
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);
if (Log.on) Log.log(Box.class, "unable to load image " + s + " at " +
Context.enter().interpreterSourceFile + ":" + Context.enter().interpreterLine);
return;
- }
+ }
if (sizetoimage) syncSizeToImage();
dirty();
}
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 */
return cachedProxyInfo;
}
+ public static synchronized ImageDecoder decodeJPEG(InputStream is, String name) {
+ return platform._decodeJPEG(is, name);
+ }
+
// Helpful font parsing stuff //////////////////////////////////////////////////////
public static class ParsedFont {
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;
}
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);
}
}
+ 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; }
-
+#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);
+}
+
+
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 {
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();
+ }
+
}
// 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>
#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)