From f4ff7c16a3b69784da7f66f6ff1be899b4a5f508 Mon Sep 17 00:00:00 2001 From: megacz Date: Fri, 30 Jan 2004 07:38:47 +0000 Subject: [PATCH] 2003/09/30 21:30:49 darcs-hash:20040130073847-2ba56-02f46a0be2a2bbd4c5298a5942d49cfc728f39a4.gz --- src/org/xwt/Box.java.pp | 18 ++++++++++ src/org/xwt/Res.java | 22 ++++++++++-- src/org/xwt/util/CachedInputStream.java | 56 +++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 src/org/xwt/util/CachedInputStream.java diff --git a/src/org/xwt/Box.java.pp b/src/org/xwt/Box.java.pp index 05c6602..7a4fc72 100644 --- a/src/org/xwt/Box.java.pp +++ b/src/org/xwt/Box.java.pp @@ -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) { diff --git a/src/org/xwt/Res.java b/src/org/xwt/Res.java index 10a920b..cd0fc86 100644 --- a/src/org/xwt/Res.java +++ b/src/org/xwt/Res.java @@ -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 index 0000000..1c2cffd --- /dev/null +++ b/src/org/xwt/util/CachedInputStream.java @@ -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; + } + } + } +} -- 1.7.10.4