2003/08/10 06:03:01
[org.ibex.core.git] / src / org / xwt / ImageDecoder.java
index 22cef92..bfcbc7e 100644 (file)
@@ -1,9 +1,11 @@
 // 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();
@@ -14,4 +16,95 @@ public interface ImageDecoder {
     /** 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();
+
 }