2003/09/30 21:30:49
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:38:47 +0000 (07:38 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 07:38:47 +0000 (07:38 +0000)
darcs-hash:20040130073847-2ba56-02f46a0be2a2bbd4c5298a5942d49cfc728f39a4.gz

src/org/xwt/Box.java.pp
src/org/xwt/Res.java
src/org/xwt/util/CachedInputStream.java [new file with mode: 0644]

index 05c6602..7a4fc72 100644 (file)
@@ -961,6 +961,16 @@ public final class Box extends JS.Scope {
                         b.dirty();
                     } });
         
+            specialBoxProperties.put("transform", new SpecialBoxProperty() {
+                    public Object get(Box b) { return b.font; }
+                    public void put(Box b, Object value) {
+                        // FIXME: translate value into a resource if it is a string
+                        b.font = value == null ? null : (Res)value;
+                        MARK_FOR_REFLOW_b;
+                        b.flags |= FONT_CHANGED_FLAG;
+                        b.dirty();
+                    } });
+        
             specialBoxProperties.put("fontsize", new SpecialBoxProperty() {
                     public Object get(Box b) { return b.font; }
                     public void put(Box b, Object value) {
@@ -971,6 +981,14 @@ public final class Box extends JS.Scope {
                         b.dirty();
                     } });
         
+            specialBoxProperties.put("strokewidth", new SpecialBoxProperty() {
+                    public Object get(Box b) { return b.strokewidth; }
+                    public void put(Box b, Object value) {
+                        if (b.strokewidth == stoi(value)) return;
+                        b.strokewidth = stoi(value);
+                        b.dirty();
+                    } });
+        
             specialBoxProperties.put("thisbox", new SpecialBoxProperty() {
                     public Object get(Box b) { return b; }
                     public void put(Box b, Object value) {
index 10a920b..cd0fc86 100644 (file)
@@ -48,7 +48,8 @@ public abstract class Res extends JS {
     public static Res stringToRes(String url) { return stringToRes(url, false); }
     public static Res stringToRes(String url, boolean permitLocalFilesystem) {
         if (url.indexOf('!') != -1)
-            return (Res)(new Zip(stringToRes(url.substring(0, url.lastIndexOf('!')))).get(url.substring(url.lastIndexOf('!') + 1)));
+            return (Res)(new Zip(stringToRes(url.substring(0, url.lastIndexOf('!')))).
+                         get(url.substring(url.lastIndexOf('!') + 1)));
         if (url.startsWith("http://")) return new HTTP(url);
         if (url.startsWith("https://")) return new HTTP(url);
         if (url.startsWith("file:") && permitLocalFilesystem) return new File(url.substring(5));
@@ -58,11 +59,26 @@ public abstract class Res extends JS {
         throw new JS.Exn("invalid resource specifier " + url);
     }
 
+    /** subclass from this if you want a CachedInputStream for each path */
+    public static abstract class CachedRes extends Res {
+        private Hash cachedInputStreams = new Hash();
+        abstract InputStream _getInputStream(String path) throws IOException;
+        public final InputStream getInputStream(String path) throws IOException {
+            CachedInputStream cis = (CachedInputStream)cachedInputStreams.get(path);
+            if (cis == null) {
+                cis = new CachedInputStream(_getInputStream(path));
+                cachedInputStreams.put(path, cis);
+            }
+            return cis.getInputStream();
+        }
+    }
+
     /** HTTP or HTTPS resource */
-    public static class HTTP extends Res {
+    public static class HTTP extends CachedRes {
         private String url;
         HTTP(String url) { this.url = url; }
-        public InputStream getInputStream(String path) throws IOException { return new org.xwt.HTTP(url + path).GET(); }
+        public InputStream _getInputStream(String path) throws IOException {
+            return new org.xwt.HTTP(url + path).GET(); }
     }
 
     /** byte arrays */
diff --git a/src/org/xwt/util/CachedInputStream.java b/src/org/xwt/util/CachedInputStream.java
new file mode 100644 (file)
index 0000000..1c2cffd
--- /dev/null
@@ -0,0 +1,56 @@
+package org.xwt.util;
+import java.io.*;
+
+/**
+ *  Wraps around an InputStream, caching the stream in a byte[] as it
+ *  is read and permitting multiple simultaneous readers
+ */
+public class CachedInputStream {
+
+    boolean filling = false;               ///< true iff some thread is blocked on us waiting for input
+    boolean eof = false;                   ///< true iff end of stream has been reached
+    byte[] cache = new byte[1024 * 128];
+    int size = 0;
+    final InputStream is;
+
+    public CachedInputStream(InputStream is) { this.is = is; }
+    public InputStream getInputStream() { return new SubStream(); }
+
+    public void grow(int newLength) {
+        if (newLength < cache.length) return;
+        byte[] newCache = new byte[cache.length + 2 * (newLength - cache.length)];
+        System.arraycopy(cache, 0, newCache, 0, size);
+        cache = newCache;
+    }
+
+    synchronized void fillCache(int howMuch) throws IOException {
+        if (filling) { try { wait(); } catch (InterruptedException e) { }; return; }
+        filling = true;
+        grow(size + howMuch);
+        int ret = is.read(cache, size, howMuch);
+        if (ret == -1) eof = true;
+        else size += ret;
+        filling = false;
+        notifyAll();
+    }
+
+    private class SubStream extends InputStream {
+        int pos = 0;
+        public int available() { return Math.max(0, size - pos); }
+        public long skip(long n) throws IOException { pos += (int)n; return n; }     // FEATURE: don't skip past EOF
+        public int read() throws IOException {                                       // FEATURE: be smarter here
+            byte[] b = new byte[1];
+            int ret = read(b, 0, 1);
+            return ret == -1 ? -1 : b[0];
+        }
+        public int read(byte[] b, int off, int len) throws IOException {
+            synchronized(CachedInputStream.this) {
+                while (pos >= size && !eof) fillCache(pos + len - size);
+                if (eof && pos == size) return -1;
+                int count = Math.min(size - pos, len);
+                System.arraycopy(cache, pos, b, off, count);
+                return count;
+            }
+        }
+    }
+}