-// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
+// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL]
package org.xwt;
import java.io.*;
+import org.xwt.js.*;
+import org.xwt.util.*;
/** Interface implemented by classes capable of decoding an image file into an int[] */
-public interface ImageDecoder {
+public abstract class ImageDecoder {
/** returns the width of the image */
public abstract int getWidth();
/** returns the data of the image, as an array of 32-bit AARRGGBB samples */
public abstract int[] getData();
+ /** loads the image described by string str, possibly blocking for a network load */
+ public static ImageDecoder getImageDecoder(String str, final JS.Callable callback) {
+
+ if (str.indexOf(':') == -1) {
+ String s = str;
+ byte[] b = Resources.getResource(Resources.resolve(s + ".png", null));
+ 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 {
+ java.lang.Thread thread = java.lang.Thread.currentThread();
+ if (!(thread instanceof ThreadMessage)) {
+ if (Log.on) Log.log(Box.class, "HTTP images can not be loaded from the foreground thread");
+ return null;
+ }
+ // FIXME: use primitives here
+ ThreadMessage mythread = (ThreadMessage)thread;
+ mythread.setPriority(java.lang.Thread.MIN_PRIORITY);
+ mythread.done.release();
+ try {
+ HTTP http = new HTTP(str);
+ final HTTP.HTTPInputStream in = http.GET();
+ final int contentLength = in.getContentLength();
+ InputStream is = new FilterInputStream(in) {
+ int bytesDownloaded = 0;
+ boolean clear = true;
+ public int read() throws IOException {
+ bytesDownloaded++;
+ return super.read();
+ }
+ public int read(byte[] b, int off, int len) throws IOException {
+ int ret = super.read(b, off, len);
+ if (ret != -1) bytesDownloaded += ret;
+ if (clear && callback != null) {
+ clear = false;
+ ThreadMessage.newthread(new JS.Callable() {
+ public Object call(JS.Array args_) throws JS.Exn {
+ try {
+ JS.Array args = new JS.Array();
+ args.addElement(new Double(bytesDownloaded));
+ args.addElement(new Double(contentLength));
+ callback.call(args);
+ } finally {
+ clear = true;
+ }
+ return null;
+ }
+ });
+ }
+ return ret;
+ }
+ };
+
+ if (str.endsWith(".gif")) return GIF.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, e);
+ return null;
+
+ } finally {
+ MessageQueue.add(mythread);
+ mythread.setPriority(java.lang.Thread.NORM_PRIORITY);
+ mythread.go.block();
+ }
+ }
+ }
+
+ /** gets an Image using getImage(), adds it to the cache, and creates a Picture from it */
+ public static Picture getPicture(String os) {
+ Picture ret = null;
+ ret = (Picture)pictureCache.get(os);
+ if (ret != null) return ret;
+ ImageDecoder id = ImageDecoder.getImageDecoder(os, null);
+ if (id == null) return null;
+ ret = Platform.createPicture(id);
+ pictureCache.put(os, ret);
+ imageToNameMap.put(ret, os);
+ return ret;
+ }
+
+ /** caches images, keyed on resource name or url */
+ public static Hash pictureCache = new Hash();
+
+ /** stores image names, keyed on image object */
+ static Hash imageToNameMap = new Hash();
+
}