From: megacz Date: Fri, 30 Jan 2004 07:35:55 +0000 (+0000) Subject: 2003/09/19 08:33:46 X-Git-Tag: RC3~599 X-Git-Url: http://git.megacz.com/?p=org.ibex.core.git;a=commitdiff_plain;h=55c3195af733f3de6b7894f4c4a96f7b50f58c11 2003/09/19 08:33:46 darcs-hash:20040130073555-2ba56-cd95a6d6c806fd8611574f4e337122e2aceed02b.gz --- diff --git a/src/org/xwt/Box.java.pp b/src/org/xwt/Box.java.pp index 4da565a..245a2c1 100644 --- a/src/org/xwt/Box.java.pp +++ b/src/org/xwt/Box.java.pp @@ -62,7 +62,7 @@ import org.xwt.translators.*; * position. * * A note on coordinates: the Box class represents regions - * internally as x,y,w,h tuples, even though the DoubleBuffer class + * internally as x,y,w,h tuples, even though the PixelBuffer class * uses x1,y1,x2,y2 tuples. */ public final class Box extends JS.Scope { @@ -126,7 +126,8 @@ public final class Box extends JS.Scope { private LENGTH hpad = 0; private LENGTH vpad = 0; private String text = null; - private String font = null; + private Res font = null; + private int fontsize = 10; private LENGTH textwidth = 0; private LENGTH textheight = 0; @@ -405,7 +406,7 @@ public final class Box extends JS.Scope { // Rendering Pipeline ///////////////////////////////////////////////////////////////////// /** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */ - void render(int parentx, int parenty, int clipx, int clipy, int clipw, int cliph, DoubleBuffer buf) { + void render(int parentx, int parenty, int clipx, int clipy, int clipw, int cliph, PixelBuffer buf) { if (Surface.abort || (flags & INVISIBLE_FLAG) != 0) return; int globalx = parentx + (parent == null ? 0 : x); int globaly = parenty + (parent == null ? 0 : y); @@ -428,7 +429,7 @@ public final class Box extends JS.Scope { else renderStretchedImage(globalx, globaly, clipx, clipy, clipw, cliph, buf); if (text != null && !text.equals("")) - renderText(x, y, clipx, clipy, clipw, cliph, buf); + renderText(globalx, globaly, clipx, clipy, clipw, cliph, buf); // now subtract the pad region from the clip region before proceeding clipw = min(max(clipx, globalx + hpad) + clipw, globalx + width - hpad) - clipx; @@ -440,7 +441,7 @@ public final class Box extends JS.Scope { b.render(globalx, globaly, clipx, clipy, clipw, cliph, buf); } - void renderStretchedImage(int globalx, int globaly, int clipx, int clipy, int clipw, int cliph, DoubleBuffer buf) { + void renderStretchedImage(int globalx, int globaly, int clipx, int clipy, int clipw, int cliph, PixelBuffer buf) { //buf.setClip(x, y, w + x, h + y); System.out.println("draw " + clipx + " " + clipy + " " + (clipx + clipw) + " " + (clipy + cliph)); buf.drawPicture(image, @@ -449,7 +450,7 @@ public final class Box extends JS.Scope { //buf.setClip(0, 0, buf.getWidth(), buf.getHeight()); } - void renderTiledImage(int globalx, int globaly, int x, int y, int w, int h, DoubleBuffer buf) { + void renderTiledImage(int globalx, int globaly, int x, int y, int w, int h, PixelBuffer buf) { int iw = image.getWidth(); int ih = image.getHeight(); for(int i=(x - x)/iw; i <= (x + w - x)/iw; i++) { @@ -471,31 +472,21 @@ public final class Box extends JS.Scope { } } - void renderText(int x, int y, int clipx, int clipy, int clipw, int cliph, DoubleBuffer buf) { - /* - // hack because (believe it or not) libgcj doesn't support UTF16. - byte[] b = new byte[text.length() * 2 + 2]; - for(int i=0; i> 8); - b[i * 2 + 1] = (byte)(((short)text.charAt(i)) & 0xff); - } - b[text.length()] = 0; - b[text.length() + 1] = 0; - */ - /* - try { - ImageDecoder id = org.xwt.translators.Font.render(new FileInputStream("COMIC.TTF"), 24, text, false); - Picture p = Platform.createPicture(id); - // FIXME: clipping (don't use setClip) - buf.drawPicture(p, - x + hpad, y + vpad, - x + hpad + p.getWidth(), y + vpad + p.getHeight(), + void renderText(int x, int y, int clipx, int clipy, int clipw, int cliph, PixelBuffer buf) { + for(int i=0; ih. The - * CharStream should be positioned immediately after the - * open bracket. - * - * If a close tag not matching this open tag is found, the - * tagname on the close tag will be returned in order to - * facilitate correcting broken HTML. Otherwise, this returns - * null. - */ - private static String parseElement(CharStream cs, JS h) throws IOException { - // scan element name - while(Character.isSpace(cs.peek())) cs.get(); - String elementName = parseElementName(cs); - - // FIXME: this might not deal correctly with EOFExceptions - boolean saveWithinLI = withinLI; - if (elementName.equals("li")) { - if (withinLI) { - cs.unread(new char[] { '<', 'l', 'i', ' ' }); - return "li"; - } else { - withinLI = true; - } - } else if (elementName.equals("ol") || elementName.equals("ul")) { - withinLI = false; - } - - h.put("$name", elementName); - if (elementName.equals("!--")) { - h.put("0", parseComment(cs)); - h.put("$numchildren", new Integer(0)); - return null; - } - - // scan attributes - while (cs.peek() != '>') { - String name = parseAttributeName(cs); - if (name.equals("")) break; - String value = expandEntities(parseAttributeValue(cs)); - h.put(name, value); - } - - // eat the close-angle bracket - cs.get(); - - // bodyless tags return here - for(int i=0; i 0) { - h.put(String.valueOf(length), expanded); - h.put("$numchildren", new Integer(++length)); - } - cdata = ""; - - } catch (EOFException e) { - String expanded = removeRedundantWhitespace(expandEntities(cdata)); - if (expanded.length() > 0) { - h.put(String.valueOf(length), expanded); - h.put("$numchildren", new Integer(++length)); - } - throw e; - } - - try { - // scan subelement - if (cs.peek() != '/') { - JS kid = new JS.Obj(); - closetag = parseElement(cs, kid); - h.put(String.valueOf(length), kid); - h.put("$numchildren", new Integer(++length)); - - // scan close-tag - } else { - cs.get(); // drop the slash - closetag = parseElementName(cs); - while(cs.get() != '>'); - } - } catch (EOFException e) { - throw e; - - } - - if (closetag != null) - return closetag.equals(elementName) ? null : closetag; - } - } - - /** Parses an element name and returns it. The CharStream should - * be positioned at the first character of the name. - */ - private static String parseElementName(CharStream cs) throws IOException { - String ret = ""; - while (cs.peek() != '>' && !Character.isSpace(cs.peek())) ret += cs.get(); - return ret.toLowerCase(); - } - - /** Parses an attribute name and returns it. The CharStream should - * be positioned at the first character of the name, possibly - * with intervening whitespace. - */ - private static String parseAttributeName(CharStream cs) throws IOException { - while(Character.isSpace(cs.peek())) cs.get(); - String ret = ""; - while(!Character.isSpace(cs.peek()) && cs.peek() != '=' && cs.peek() != '>') ret += cs.get(); - return ret.toLowerCase(); - } - - /** Parses an attribute value and returns it. The CharStream - * should be positioned at the equals sign, possibly with - * intervening whitespace. - */ - private static String parseAttributeValue(CharStream cs) throws IOException { - - // eat whitespace and equals sign - while(Character.isSpace(cs.peek())) cs.get(); - if (cs.peek() != '=') return ""; - cs.get(); - while(Character.isSpace(cs.peek())) cs.get(); - - boolean doublequoted = false; - boolean singlequoted = false; - String ret = ""; - - if (cs.peek() == '\"') { doublequoted = true; cs.get(); } - else if (cs.peek() == '\'') { singlequoted = true; cs.get(); } - - while(true) { - char c = cs.peek(); - if (!doublequoted && !singlequoted && (Character.isSpace(c) || c == '>')) break; - if (singlequoted && c == '\'') { cs.get(); break; } - if (doublequoted && c == '\"') { cs.get(); break; } - ret += cs.get(); - } - return ret; - } - - /** Parses a comment and returns its body. The CharStream should - * be positioned immediately after the <!-- - */ - private static String parseComment(CharStream cs) throws IOException { - int dashes = 0; - String ret = ""; - while(true) { - char c = cs.get(); - if (c == '>' && dashes == 2) return ret.substring(0, ret.length() - 2); - if (c == '-') dashes++; - else dashes = 0; - ret += c; - } - } - - /** Expands all SGML entities in string s */ - public static String expandEntities(String s) throws IOException { - if (s.indexOf('&') == -1) return s; - StringBuffer sb = new StringBuffer(); - int i=0; - int nextamp = 0; - while(nextamp != -1) { - nextamp = s.indexOf('&', i); - sb.append(nextamp == -1 ? s.substring(i) : s.substring(i, nextamp)); - if (nextamp == -1) break; - if (s.regionMatches(nextamp, "&", 0, 5)) { - sb.append("&"); - i = nextamp + 5; - } else if (s.regionMatches(nextamp, ">", 0, 4)) { - sb.append(">"); - i = nextamp + 4; - } else if (s.regionMatches(nextamp, "<", 0, 4)) { - sb.append("<"); - i = nextamp + 4; - } else if (s.regionMatches(nextamp, """, 0, 6)) { - sb.append("\""); - i = nextamp + 6; - } else if (s.regionMatches(nextamp, " ", 0, 6)) { - // FIXME: should have a way to indicate this... - sb.append(" "); - i = nextamp + 6; - } else { - sb.append("&"); - i = nextamp + 1; - } - } - return sb.toString(); - } - - // FIXME double check this - /** removes all redundant whitespace */ - private static String removeRedundantWhitespace(String s) { - - if (s.indexOf(' ') == -1 && s.indexOf('\n') == -1 && s.indexOf('\t') == -1 && s.indexOf('\r') == -1) return s; - - int len = s.length(); - if (cbuf == null || cbuf.length < len) { - cbuf = new char[len * 2]; - sbuf = new StringBuffer(len * 2); - } - sbuf.setLength(0); - s.getChars(0, len, cbuf, 0); - - int last = 0; - boolean lastWasWhitespace = false; - for(int i=0; i= arr.length) return true; + for(int i=0; i= d1 && day <= d2) || + (d1 > d2 && (day >= d1 || day <= d2))) ? + Boolean.TRUE : Boolean.FALSE; + } + }; + + private static final JS.Callable dateRange = new JS.Callable() { + public Object call(org.xwt.js.JS.Array args) throws JS.Exn { + throw new JS.Exn("XWT does not support dateRange() in PAC scripts"); + } + }; + + private static final JS.Callable timeRange = new JS.Callable() { + public Object call(org.xwt.js.JS.Array args) throws JS.Exn { + throw new JS.Exn("XWT does not support timeRange() in PAC scripts"); + } + }; + + } + + } + } diff --git a/src/org/xwt/DoubleBuffer.java b/src/org/xwt/PixelBuffer.java similarity index 100% rename from src/org/xwt/DoubleBuffer.java rename to src/org/xwt/PixelBuffer.java diff --git a/src/org/xwt/Platform.java b/src/org/xwt/Platform.java index 31062e0..f081948 100644 --- a/src/org/xwt/Platform.java +++ b/src/org/xwt/Platform.java @@ -34,7 +34,7 @@ public class Platform { static boolean alreadyDetectedProxy = false; /** the result of proxy autodetection */ - static Proxy cachedProxyInfo = null; + static HTTP.Proxy cachedProxyInfo = null; /** the current build */ public static String build = "unknown"; @@ -119,7 +119,7 @@ public class Platform { /** creates and returns a doublebuffer 'belonging' to owner; we need to associate PixelBuffers to surfaces * due to AWT 1.1 requirements (definately for Navigator, possibly also for MSJVM). */ - protected PixelBuffer _createDoubleBuffer(int w, int h, Surface owner) { return null; } + protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) { return null; } /** creates and returns a new surface */ protected Surface _createSurface(Box b, boolean framed) { return null; } @@ -201,7 +201,7 @@ public class Platform { } /** Returns null if XWT should always use direct connection; otherwise returns a ProxyInfo object with proxy settings */ - protected synchronized Proxy _detectProxy() { return null; } + protected synchronized HTTP.Proxy _detectProxy() { return null; } /** displays a platform-specific "open file" dialog and returns the chosen filename, or null if the user hit cancel */ protected String _fileDialog(String suggestedFileName, boolean write) { return null; } @@ -316,7 +316,7 @@ public class Platform { public static int getScreenHeight() { return platform._getScreenHeight(); } /** creates and returns a doublebuffer 'belonging' to owner */ - public static PixelBuffer createDoubleBuffer(int w, int h, Surface s) { return platform._createDoubleBuffer(w, h, s); } + public static PixelBuffer createPixelBuffer(int w, int h, Surface s) { return platform._createPixelBuffer(w, h, s); } /** creates and returns a picture */ public static Picture createPicture(int[] data, int w, int h) { return platform._createPicture(data, w, h); } @@ -418,14 +418,14 @@ public class Platform { } /** detects proxy settings */ - public static synchronized Proxy detectProxy() { + public static synchronized HTTP.Proxy detectProxy() { if (cachedProxyInfo != null) return cachedProxyInfo; if (alreadyDetectedProxy) return null; alreadyDetectedProxy = true; if (Log.on) Log.log(Platform.class, "attempting environment-variable DNS proxy detection"); - cachedProxyInfo = Proxy.detectProxyViaManual(); + cachedProxyInfo = HTTP.Proxy.detectProxyViaManual(); if (cachedProxyInfo != null) return cachedProxyInfo; if (Log.on) Log.log(Platform.class, "attempting " + platform.getClass().getName() + " proxy detection"); diff --git a/src/org/xwt/Proxy.java b/src/org/xwt/Proxy.java deleted file mode 100644 index 8409fa5..0000000 --- a/src/org/xwt/Proxy.java +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] -package org.xwt; - -import java.net.*; -import java.io.*; -import java.util.*; -import org.xwt.js.*; -import org.xwt.util.*; -import org.bouncycastle.util.encoders.Base64; - -/** encapsulates most of the proxy logic; some is shared in HTTP.java */ -public class Proxy { - - public Proxy() { } - - /** the HTTP Proxy host to use */ - public String httpProxyHost = null; - - /** the HTTP Proxy port to use */ - public int httpProxyPort = -1; - - /** if a seperate proxy should be used for HTTPS, this is the hostname; otherwise, httpProxyHost is used */ - public String httpsProxyHost = null; - - /** if a seperate proxy should be used for HTTPS, this is the port */ - public int httpsProxyPort = -1; - - /** the SOCKS Proxy Host to use */ - public String socksProxyHost = null; - - /** the SOCKS Proxy Port to use */ - public int socksProxyPort = -1; - - /** hosts to be excluded from proxy use; wildcards permitted */ - public String[] excluded = null; - - /** the PAC script */ - public JS.Callable proxyAutoConfigFunction = null; - - public static Proxy detectProxyViaManual() { - Proxy ret = new Proxy(); - - ret.httpProxyHost = Platform.getEnv("http_proxy"); - if (ret.httpProxyHost != null) { - if (ret.httpProxyHost.startsWith("http://")) ret.httpProxyHost = ret.httpProxyHost.substring(7); - if (ret.httpProxyHost.endsWith("/")) ret.httpProxyHost = ret.httpProxyHost.substring(0, ret.httpProxyHost.length() - 1); - if (ret.httpProxyHost.indexOf(':') != -1) { - ret.httpProxyPort = Integer.parseInt(ret.httpProxyHost.substring(ret.httpProxyHost.indexOf(':') + 1)); - ret.httpProxyHost = ret.httpProxyHost.substring(0, ret.httpProxyHost.indexOf(':')); - } else { - ret.httpProxyPort = 80; - } - } - - ret.httpsProxyHost = Platform.getEnv("https_proxy"); - if (ret.httpsProxyHost != null) { - if (ret.httpsProxyHost.startsWith("https://")) ret.httpsProxyHost = ret.httpsProxyHost.substring(7); - if (ret.httpsProxyHost.endsWith("/")) ret.httpsProxyHost = ret.httpsProxyHost.substring(0, ret.httpsProxyHost.length() - 1); - if (ret.httpsProxyHost.indexOf(':') != -1) { - ret.httpsProxyPort = Integer.parseInt(ret.httpsProxyHost.substring(ret.httpsProxyHost.indexOf(':') + 1)); - ret.httpsProxyHost = ret.httpsProxyHost.substring(0, ret.httpsProxyHost.indexOf(':')); - } else { - ret.httpsProxyPort = 80; - } - } - - ret.socksProxyHost = Platform.getEnv("socks_proxy"); - if (ret.socksProxyHost != null) { - if (ret.socksProxyHost.startsWith("socks://")) ret.socksProxyHost = ret.socksProxyHost.substring(7); - if (ret.socksProxyHost.endsWith("/")) ret.socksProxyHost = ret.socksProxyHost.substring(0, ret.socksProxyHost.length() - 1); - if (ret.socksProxyHost.indexOf(':') != -1) { - ret.socksProxyPort = Integer.parseInt(ret.socksProxyHost.substring(ret.socksProxyHost.indexOf(':') + 1)); - ret.socksProxyHost = ret.socksProxyHost.substring(0, ret.socksProxyHost.indexOf(':')); - } else { - ret.socksProxyPort = 80; - } - } - - String noproxy = Platform.getEnv("no_proxy"); - if (noproxy != null) { - StringTokenizer st = new StringTokenizer(noproxy, ","); - ret.excluded = new String[st.countTokens()]; - for(int i=0; st.hasMoreTokens(); i++) ret.excluded[i] = st.nextToken(); - } - - if (ret.httpProxyHost == null && ret.socksProxyHost == null) return null; - return ret; - } - - public static JS.Scope proxyAutoConfigRootScope = new ProxyAutoConfigRootScope(); - public static JS.Callable getProxyAutoConfigFunction(String url) { - try { - BufferedReader br = new BufferedReader(new InputStreamReader(new HTTP(url, true).GET())); - String s = null; - String script = ""; - while((s = br.readLine()) != null) script += s + "\n"; - if (Log.on) Log.log(Proxy.class, "successfully retrieved WPAD PAC:"); - if (Log.on) Log.log(Proxy.class, script); - - // MS CARP hack - Vector carpHosts = new Vector(); - for(int i=0; i= arr.length) return true; - for(int i=0; i= d1 && day <= d2) || - (d1 > d2 && (day >= d1 || day <= d2))) ? - Boolean.TRUE : Boolean.FALSE; - } - }; - - private static final JS.Callable dateRange = new JS.Callable() { - public Object call(org.xwt.js.JS.Array args) throws JS.Exn { - throw new JS.Exn("XWT does not support dateRange() in PAC scripts"); - } - }; - - private static final JS.Callable timeRange = new JS.Callable() { - public Object call(org.xwt.js.JS.Array args) throws JS.Exn { - throw new JS.Exn("XWT does not support timeRange() in PAC scripts"); - } - }; - - } - -} diff --git a/src/org/xwt/Res.java b/src/org/xwt/Res.java index 5b1fc5f..f0b25bf 100644 --- a/src/org/xwt/Res.java +++ b/src/org/xwt/Res.java @@ -2,30 +2,32 @@ package org.xwt; import java.io.*; +import java.util.*; +import java.util.zip.*; import org.xwt.js.*; +import org.xwt.util.*; // FIXME: ByteStream fileName property /** base class for XWT resources */ public abstract class Res extends JS { - public String toString() { return "Resource, source=FIXME"; } - - public final InputStream getInputStream() { return getInputStream(""); } + public final InputStream getInputStream() throws IOException { return getInputStream(""); } public Res graft(Object newResource) { throw new JS.Exn("cannot graft onto this resource"); } public Object get(Object key) { return new Ref(this, key); } public void put(Object key, Object val) { throw new JS.Exn("cannot put to a resource"); } public Object[] keys() { throw new JS.Exn("cannot enumerate a resource"); } - public abstract InputStream getInputStream(String path) { return getInputStream(""); } - public abstract Res addExtension(String extension); + public abstract InputStream getInputStream(String path) throws IOException; + //public abstract Res addExtension(String extension); public static Res stringToRes(String url) { - if (url.indexOf('!') == -1) - return new Zip(stringToRes(url.substring(0, url.lastIndexOf('!'))), - url.substring(url.lastIndexOf('!') + 1)); + if (url.indexOf('!') != -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:")) return new File(url.substring(5)); + if (url.startsWith("cab:")) return new CAB(stringToRes(url.substring(4))); throw new JS.Exn("invalid resource specifier"); } @@ -33,14 +35,21 @@ public abstract class Res extends JS { public static class HTTP extends Res { private String url; HTTP(String url) { this.url = url; } - public InputStream getInputStream(String path) { return new HTTP(url + path).GET(); } + public InputStream getInputStream(String path) throws IOException { return new org.xwt.HTTP(url + path).GET(); } + } + + // FIXME: dangerous + /** a file */ + public static class File extends Res { + private String path; + File(String path) { this.path = path; } + public InputStream getInputStream(String rest) throws IOException { return new FileInputStream((path + rest).replace('/', java.io.File.separatorChar)); } } /** wrap a Res around a preexisting InputStream */ public static class IS extends Res { InputStream parent; IS(InputStream parent) { this.parent = parent; } - public InputStream getInputStream() { return parent; } public InputStream getInputStream(String path) { if (!"".equals(path)) throw new JS.Exn("can't access subresources of IS"); return parent; @@ -51,7 +60,7 @@ public abstract class Res extends JS { public static class Zip extends Res { private Res parent; Zip(Res parent) { this.parent = parent; } - public InputStream getInputStream(String path) { + public InputStream getInputStream(String path) throws IOException { ZipInputStream zis = new ZipInputStream(parent.getInputStream()); ZipEntry ze = zis.getNextEntry(); while(ze != null && !ze.getName().equals(path)) ze = zis.getNextEntry(); @@ -65,7 +74,7 @@ public abstract class Res extends JS { Res parent; Object key; Ref(Res parent, Object key) { this.parent = parent; this.key = key; } - public InputStream getInputStream(path) { + public InputStream getInputStream(String path) throws IOException { return parent.getInputStream("/" + key + path); } public Res graft(Object newResource) { return new Graft(parent, key, newResource); } @@ -79,12 +88,32 @@ public abstract class Res extends JS { Graft(Res graftee, Object key, Object val) { this.graftee = graftee; replaced_key = key; replaced_val = val; } public boolean equals(Object o) { return (this == o || graftee.equals(o)); } + public int hashCode() { return graftee.hashCode(); } + public InputStream getInputStream(String s) throws IOException { return graftee.getInputStream(s); } public Object get(Object key) { return replaced_key.equals(key) ? replaced_val : graftee.get(key); } } - /////////////// bytestream + /** unpacks a Microsoft CAB file (possibly embedded in another file; we scan for 'MSCF' */ + public static class CAB extends Res { + private Res parent; + CAB(Res parent) { this.parent = parent; } + private int swap_endian(int i) { + return ((i & 0xff) << 24) | ((i & 0xff00) << 8) | ((i & 0xff0000) >>> 8) | (i >>> 24); + } + public InputStream getInputStream(String path) throws IOException { + InputStream is = new InputStream(parent.getInputStream()); + byte[] scan = new byte[4]; + while(scan[0] != 'M' || scan[1] != 'S' || scan[2] != 'C' || scan[3] != 'F') { + System.arraycopy(scan, 1, scan, 0, 3); + int read = is.read(); + if (read == -1) throw new JS.Exn("MSCF header tag not found in file"); + scan[3] = (byte)read; + } + return org.xwt.util.CAB.getFileInputStream(is, path); + } + } public Object callMethod(Object method, Array args, boolean checkOnly) throws JS.Exn { if (method.equals("getUTF")) { @@ -102,11 +131,11 @@ public abstract class Res extends JS { } return caw.toString(); } catch (IOException e) { - if (Log.on) Log.log(ByteStream.class, "IO Exception while reading from file"); - if (Log.on) Log.log(ByteStream.class, e); - throw new JS.Exn("error while reading from ByteStream"); + if (Log.on) Log.log(Res.class, "IO Exception while reading from file"); + if (Log.on) Log.log(Res.class, e); + throw new JS.Exn("error while reading from Resource"); } - } else if (name.equals("getDOM")) { + } else if (method.equals("getDOM")) { if (checkOnly) return Boolean.TRUE; if (args.length() != 0) return null; return new XMLHelper().doParse(); @@ -155,9 +184,9 @@ public abstract class Res extends JS { } catch (XML.XMLException e) { throw new JS.Exn("error parsing XML: " + e.toString()); } catch (IOException e) { - if (Log.on) Log.log(ByteStream.class, "IO Exception while reading from file"); - if (Log.on) Log.log(ByteStream.class, e); - throw new JS.Exn("error reading from ByteStream"); + if (Log.on) Log.log(this, "IO Exception while reading from file"); + if (Log.on) Log.log(this, e); + throw new JS.Exn("error reading from Resource"); } return obStack.size() >= 1 ? (JS)obStack.elementAt(0) : null; } diff --git a/src/org/xwt/SOAP.java b/src/org/xwt/SOAP.java index 1678068..5b969b4 100644 --- a/src/org/xwt/SOAP.java +++ b/src/org/xwt/SOAP.java @@ -90,11 +90,13 @@ class SOAP extends XMLRPC { objects.addElement(new String(content.getBuf(), 0, content.size()).intern()); content.reset(); + // FIXME + /* } else if (me instanceof byte[]) { objects.removeElementAt(objects.size() - 1); objects.addElement(new ByteStream(Base64.decode(new String(content.getBuf(), 0, content.size())))); content.reset(); - + */ } else if (me instanceof Integer) { objects.removeElementAt(objects.size() - 1); objects.addElement(new Integer(new String(content.getBuf(), 0, content.size()))); @@ -177,6 +179,7 @@ class SOAP extends XMLRPC { sb.append(((Boolean)o).booleanValue() ? "true" : "false"); sb.append("\r\n"); + /* FIXME } else if (o instanceof ByteStream) { try { sb.append(" <" + name + " xsi:type=\"SOAP-ENC:base64\">\r\n"); @@ -201,7 +204,7 @@ class SOAP extends XMLRPC { if (Log.on) Log.log(this, e); throw new JS.Exn("caught IOException while attempting to send a ByteStream via SOAP"); } - + */ } else if (o instanceof String) { sb.append(" <" + name + " xsi:type=\"xsd:string\">"); String s = (String)o; diff --git a/src/org/xwt/SVG.java b/src/org/xwt/SVG.java deleted file mode 100644 index 9b94609..0000000 --- a/src/org/xwt/SVG.java +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2003 Adam Megacz, see the COPYING file for licensing [GPL] -package org.xwt; -import java.util.*; - -public class SVG { - - /** Copied verbatim from the SVG specification */ - public static Hashtable colors = new Hashtable(400); - static { - colors.put("aliceblue", new Integer((240 << 16) | (248 << 8) | 255)); - colors.put("antiquewhite", new Integer((250 << 16) | (235 << 8) | 215)); - colors.put("aqua", new Integer((0 << 16) | (255 << 8) | 255)); - colors.put("aquamarine", new Integer((127 << 16) | (255 << 8) | 212)); - colors.put("azure", new Integer((240 << 16) | (255 << 8) | 255)); - colors.put("beige", new Integer((245 << 16) | (245 << 8) | 220)); - colors.put("bisque", new Integer((255 << 16) | (228 << 8) | 196)); - colors.put("black", new Integer((0 << 16) | (0 << 8) | 0)); - colors.put("blanchedalmond", new Integer((255 << 16) | (235 << 8) | 205)); - colors.put("blue", new Integer((0 << 16) | (0 << 8) | 255)); - colors.put("blueviolet", new Integer((138 << 16) | (43 << 8) | 226)); - colors.put("brown", new Integer((165 << 16) | (42 << 8) | 42)); - colors.put("burlywood", new Integer((222 << 16) | (184 << 8) | 135)); - colors.put("cadetblue", new Integer((95 << 16) | (158 << 8) | 160)); - colors.put("chartreuse", new Integer((127 << 16) | (255 << 8) | 0)); - colors.put("chocolate", new Integer((210 << 16) | (105 << 8) | 30)); - colors.put("coral", new Integer((255 << 16) | (127 << 8) | 80)); - colors.put("cornflowerblue", new Integer((100 << 16) | (149 << 8) | 237)); - colors.put("cornsilk", new Integer((255 << 16) | (248 << 8) | 220)); - colors.put("crimson", new Integer((220 << 16) | (20 << 8) | 60)); - colors.put("cyan", new Integer((0 << 16) | (255 << 8) | 255)); - colors.put("darkblue", new Integer((0 << 16) | (0 << 8) | 139)); - colors.put("darkcyan", new Integer((0 << 16) | (139 << 8) | 139)); - colors.put("darkgoldenrod", new Integer((184 << 16) | (134 << 8) | 11)); - colors.put("darkgray", new Integer((169 << 16) | (169 << 8) | 169)); - colors.put("darkgreen", new Integer((0 << 16) | (100 << 8) | 0)); - colors.put("darkgrey", new Integer((169 << 16) | (169 << 8) | 169)); - colors.put("darkkhaki", new Integer((189 << 16) | (183 << 8) | 107)); - colors.put("darkmagenta", new Integer((139 << 16) | (0 << 8) | 139)); - colors.put("darkolivegreen", new Integer((85 << 16) | (107 << 8) | 47)); - colors.put("darkorange", new Integer((255 << 16) | (140 << 8) | 0)); - colors.put("darkorchid", new Integer((153 << 16) | (50 << 8) | 204)); - colors.put("darkred", new Integer((139 << 16) | (0 << 8) | 0)); - colors.put("darksalmon", new Integer((233 << 16) | (150 << 8) | 122)); - colors.put("darkseagreen", new Integer((143 << 16) | (188 << 8) | 143)); - colors.put("darkslateblue", new Integer((72 << 16) | (61 << 8) | 139)); - colors.put("darkslategray", new Integer((47 << 16) | (79 << 8) | 79)); - colors.put("darkslategrey", new Integer((47 << 16) | (79 << 8) | 79)); - colors.put("darkturquoise", new Integer((0 << 16) | (206 << 8) | 209)); - colors.put("darkviolet", new Integer((148 << 16) | (0 << 8) | 211)); - colors.put("deeppink", new Integer((255 << 16) | (20 << 8) | 147)); - colors.put("deepskyblue", new Integer((0 << 16) | (191 << 8) | 255)); - colors.put("dimgray", new Integer((105 << 16) | (105 << 8) | 105)); - colors.put("dimgrey", new Integer((105 << 16) | (105 << 8) | 105)); - colors.put("dodgerblue", new Integer((30 << 16) | (144 << 8) | 255)); - colors.put("firebrick", new Integer((178 << 16) | (34 << 8) | 34)); - colors.put("floralwhite", new Integer((255 << 16) | (250 << 8) | 240)); - colors.put("forestgreen", new Integer((34 << 16) | (139 << 8) | 34)); - colors.put("fuchsia", new Integer((255 << 16) | (0 << 8) | 255)); - colors.put("gainsboro", new Integer((220 << 16) | (220 << 8) | 220)); - colors.put("ghostwhite", new Integer((248 << 16) | (248 << 8) | 255)); - colors.put("gold", new Integer((255 << 16) | (215 << 8) | 0)); - colors.put("goldenrod", new Integer((218 << 16) | (165 << 8) | 32)); - colors.put("gray", new Integer((128 << 16) | (128 << 8) | 128)); - colors.put("grey", new Integer((128 << 16) | (128 << 8) | 128)); - colors.put("green", new Integer((0 << 16) | (128 << 8) | 0)); - colors.put("greenyellow", new Integer((173 << 16) | (255 << 8) | 47)); - colors.put("honeydew", new Integer((240 << 16) | (255 << 8) | 240)); - colors.put("hotpink", new Integer((255 << 16) | (105 << 8) | 180)); - colors.put("indianred", new Integer((205 << 16) | (92 << 8) | 92)); - colors.put("indigo", new Integer((75 << 16) | (0 << 8) | 130)); - colors.put("ivory", new Integer((255 << 16) | (255 << 8) | 240)); - colors.put("khaki", new Integer((240 << 16) | (230 << 8) | 140)); - colors.put("lavender", new Integer((230 << 16) | (230 << 8) | 250)); - colors.put("lavenderblush", new Integer((255 << 16) | (240 << 8) | 245)); - colors.put("lawngreen", new Integer((124 << 16) | (252 << 8) | 0)); - colors.put("lemonchiffon", new Integer((255 << 16) | (250 << 8) | 205)); - colors.put("lightblue", new Integer((173 << 16) | (216 << 8) | 230)); - colors.put("lightcoral", new Integer((240 << 16) | (128 << 8) | 128)); - colors.put("lightcyan", new Integer((224 << 16) | (255 << 8) | 255)); - colors.put("lightgoldenrodyellow", new Integer((250 << 16) | (250 << 8) | 210)); - colors.put("lightgray", new Integer((211 << 16) | (211 << 8) | 211)); - colors.put("lightgreen", new Integer((144 << 16) | (238 << 8) | 144)); - colors.put("lightgrey", new Integer((211 << 16) | (211 << 8) | 211)); - colors.put("lightpink", new Integer((255 << 16) | (182 << 8) | 193)); - colors.put("lightsalmon", new Integer((255 << 16) | (160 << 8) | 122)); - colors.put("lightseagreen", new Integer((32 << 16) | (178 << 8) | 170)); - colors.put("lightskyblue", new Integer((135 << 16) | (206 << 8) | 250)); - colors.put("lightslategray", new Integer((119 << 16) | (136 << 8) | 153)); - colors.put("lightslategrey", new Integer((119 << 16) | (136 << 8) | 153)); - colors.put("lightsteelblue", new Integer((176 << 16) | (196 << 8) | 222)); - colors.put("lightyellow", new Integer((255 << 16) | (255 << 8) | 224)); - colors.put("lime", new Integer((0 << 16) | (255 << 8) | 0)); - colors.put("limegreen", new Integer((50 << 16) | (205 << 8) | 50)); - colors.put("linen", new Integer((250 << 16) | (240 << 8) | 230)); - colors.put("magenta", new Integer((255 << 16) | (0 << 8) | 255)); - colors.put("maroon", new Integer((128 << 16) | (0 << 8) | 0)); - colors.put("mediumaquamarine", new Integer((102 << 16) | (205 << 8) | 170)); - colors.put("mediumblue", new Integer((0 << 16) | (0 << 8) | 205)); - colors.put("mediumorchid", new Integer((186 << 16) | (85 << 8) | 211)); - colors.put("mediumpurple", new Integer((147 << 16) | (112 << 8) | 219)); - colors.put("mediumseagreen", new Integer((60 << 16) | (179 << 8) | 113)); - colors.put("mediumslateblue", new Integer((123 << 16) | (104 << 8) | 238)); - colors.put("mediumspringgreen", new Integer((0 << 16) | (250 << 8) | 154)); - colors.put("mediumturquoise", new Integer((72 << 16) | (209 << 8) | 204)); - colors.put("mediumvioletred", new Integer((199 << 16) | (21 << 8) | 133)); - colors.put("midnightblue", new Integer((25 << 16) | (25 << 8) | 112)); - colors.put("mintcream", new Integer((245 << 16) | (255 << 8) | 250)); - colors.put("mistyrose", new Integer((255 << 16) | (228 << 8) | 225)); - colors.put("moccasin", new Integer((255 << 16) | (228 << 8) | 181)); - colors.put("navajowhite", new Integer((255 << 16) | (222 << 8) | 173)); - colors.put("navy", new Integer((0 << 16) | (0 << 8) | 128)); - colors.put("oldlace", new Integer((253 << 16) | (245 << 8) | 230)); - colors.put("olive", new Integer((128 << 16) | (128 << 8) | 0)); - colors.put("olivedrab", new Integer((107 << 16) | (142 << 8) | 35)); - colors.put("orange", new Integer((255 << 16) | (165 << 8) | 0)); - colors.put("orangered", new Integer((255 << 16) | (69 << 8) | 0)); - colors.put("orchid", new Integer((218 << 16) | (112 << 8) | 214)); - colors.put("palegoldenrod", new Integer((238 << 16) | (232 << 8) | 170)); - colors.put("palegreen", new Integer((152 << 16) | (251 << 8) | 152)); - colors.put("paleturquoise", new Integer((175 << 16) | (238 << 8) | 238)); - colors.put("palevioletred", new Integer((219 << 16) | (112 << 8) | 147)); - colors.put("papayawhip", new Integer((255 << 16) | (239 << 8) | 213)); - colors.put("peachpuff", new Integer((255 << 16) | (218 << 8) | 185)); - colors.put("peru", new Integer((205 << 16) | (133 << 8) | 63)); - colors.put("pink", new Integer((255 << 16) | (192 << 8) | 203)); - colors.put("plum", new Integer((221 << 16) | (160 << 8) | 221)); - colors.put("powderblue", new Integer((176 << 16) | (224 << 8) | 230)); - colors.put("purple", new Integer((128 << 16) | (0 << 8) | 128)); - colors.put("red", new Integer((255 << 16) | (0 << 8) | 0)); - colors.put("rosybrown", new Integer((188 << 16) | (143 << 8) | 143)); - colors.put("royalblue", new Integer((65 << 16) | (105 << 8) | 225)); - colors.put("saddlebrown", new Integer((139 << 16) | (69 << 8) | 19)); - colors.put("salmon", new Integer((250 << 16) | (128 << 8) | 114)); - colors.put("sandybrown", new Integer((244 << 16) | (164 << 8) | 96)); - colors.put("seagreen", new Integer((46 << 16) | (139 << 8) | 87)); - colors.put("seashell", new Integer((255 << 16) | (245 << 8) | 238)); - colors.put("sienna", new Integer((160 << 16) | (82 << 8) | 45)); - colors.put("silver", new Integer((192 << 16) | (192 << 8) | 192)); - colors.put("skyblue", new Integer((135 << 16) | (206 << 8) | 235)); - colors.put("slateblue", new Integer((106 << 16) | (90 << 8) | 205)); - colors.put("slategray", new Integer((112 << 16) | (128 << 8) | 144)); - colors.put("slategrey", new Integer((112 << 16) | (128 << 8) | 144)); - colors.put("snow", new Integer((255 << 16) | (250 << 8) | 250)); - colors.put("springgreen", new Integer((0 << 16) | (255 << 8) | 127)); - colors.put("steelblue", new Integer((70 << 16) | (130 << 8) | 180)); - colors.put("tan", new Integer((210 << 16) | (180 << 8) | 140)); - colors.put("teal", new Integer((0 << 16) | (128 << 8) | 128)); - colors.put("thistle", new Integer((216 << 16) | (191 << 8) | 216)); - colors.put("tomato", new Integer((255 << 16) | (99 << 8) | 71)); - colors.put("turquoise", new Integer((64 << 16) | (224 << 8) | 208)); - colors.put("violet", new Integer((238 << 16) | (130 << 8) | 238)); - colors.put("wheat", new Integer((245 << 16) | (222 << 8) | 179)); - colors.put("white", new Integer((255 << 16) | (255 << 8) | 255)); - colors.put("whitesmoke", new Integer((245 << 16) | (245 << 8) | 245)); - colors.put("yellow", new Integer((255 << 16) | (255 << 8) | 0)); - colors.put("yellowgreen", new Integer((154 << 16) | (205 << 8) | 50)); - } - -} diff --git a/src/org/xwt/VectorGraphics.java b/src/org/xwt/VectorGraphics.java new file mode 100644 index 0000000..cd62d89 --- /dev/null +++ b/src/org/xwt/VectorGraphics.java @@ -0,0 +1,1138 @@ +// Copyright 2002 Adam Megacz, see the COPYING file for licensing [GPL] +package org.xwt; +import org.xwt.util.*; +import java.util.*; + +// NOTE: we have to make sure that a box is never smaller than the +// bounding box of its path unless the user specifically forced +// it to be so. + +// FIXME: fracture when realizing instead of when parsing? +/* + v1.0 + - Base64 "data:" URL support + - textpath + - gradients + - patterns + - clipping/masking + - filters (filtering of a group must be performed AFTER the group is assembled; sep. canvas) + - style sheets + + v1.1 + - markers (do this in the parser; remember the order: fill, stroke, marker) + - bump caps [requires Paint that can fill circles...] [remember to distinguish between closed/unclosed] + - line joins + - mitre (hard) + - bevel (easy) + - bump (easy, but requires 'round' Paint) + - subtree sharing? otherwise the memory consumption might be outrageous... clone="" attribute? + - better clipping + - intersect clip regions (linearity) + - clip on trapezoids, not pixels + - faster gradients and patterns: + - transform each corner of the trapezoid and then interpolate + + */ + +/** XWT's fully conformant Static SVG Viewer; see SVG spec, section G.7 */ +public final class VectorGraphics { + /* + // Public entry points ///////////////////////////////////////////////////////////////// + + // FIXME + public static SVG.Font currentFont = null; + + public static VectorPath parseVectorPath(String s) { + PathTokenizer t = new PathTokenizer(s); + VectorPath ret = new VectorPath(); + char last_command = 'M'; + boolean first = true; + while(t.hasMoreTokens()) { + char command = t.parseCommand(); + if (first && command != 'M') throw new RuntimeException("the first command of a path must be 'M'"); + first = false; + boolean relative = Character.toLowerCase(command) == command; + command = Character.toLowerCase(command); + ret.parseSingleCommandAndArguments(t, command, relative); + last_command = command; + } + return ret; + } + + public static void parseNode(String name, String[] keys, Object[] vals, Template t) { + Hash h = new Hash(); + for(int i=0; iname property * / + Hashtable glyphByName = new Hashtable(); + + / ** linked list of glyphs, stored by the first character of their unicode property * / + Hashtable glyphByUnicode = new Hashtable(); + + / ** a Glyph in an SVG font * / + public static class Glyph { + + // FIXME: lang attribute + boolean isVerticallyOriented = false; + Template t = null; + Box b = null; + + float horiz_adv_x = 0; + float vert_origin_x = 0; + float vert_origin_y = 0; + float vert_adv_y = 0; + + String unicode = null; + + / ** forms the linked list in glyphByUnicode; glyphs appear in the order specified in the font * / + public Glyph next = null; + + Glyph(String name, String unicode, Template t, SVG.Font f) { + if (unicode != null) + if (f.glyphByUnicode.get(unicode.substring(0, 1)) == null) { + f.glyphByUnicode.put(unicode.substring(0, 1), this); + } else { + Glyph g; + for(g = (Glyph)f.glyphByUnicode.get(unicode.substring(0, 1)); g.next != null; g = g.next); + g.next = this; + } + if (name != null) f.glyphByUnicode.put(name, this); + this.unicode = unicode; + this.t = t; + horiz_adv_x = f.horiz_adv_x; + vert_origin_x = f.vert_origin_x; + vert_origin_y = f.vert_origin_y; + vert_adv_y = f.vert_adv_y; + } + public void render(DoubleBuffer buf, int x, int y, int fillcolor, int strokecolor, float scaleFactor) { + // FEATURE: make b double-buffered for increased performance + if (b == null) { + b = new Box(t, new org.xwt.util.Vec(), new org.xwt.util.Vec(), null, 0, 0); + b.put("absolute", Boolean.TRUE); + b.prerender(); + t = null; + } + // FIXME + b.put("width", new Integer(1000)); + b.put("height", new Integer(1000)); + b.fillcolor = fillcolor; + b.strokecolor = strokecolor; + + // we toss an extra flip on the ctm so that fonts stick "up" instead of down + b.render(0, 0, buf.getWidth(), buf.getHeight(), buf, + Affine.flip(false, true).multiply(Affine.scale(scaleFactor, scaleFactor).multiply(Affine.translate(x, y))).multiply(buf.a)); + } + } + } + + // Affine ////////////////////////////////////////////////////////////////////////////// + + / ** an affine transform; all operations are destructive * / + public static final class Affine { + + // [ a b e ] + // [ c d f ] + // [ 0 0 1 ] + public float a, b, c, d, e, f; + + Affine(float _a, float _b, float _c, float _d, float _e, float _f) { a = _a; b = _b; c = _c; d = _d; e = _e; f = _f; } + public String toString() { return "[ " + a + ", " + b + ", " + c + ", " + d + ", " + e + ", " + f + " ]"; } + public Affine copy() { return new Affine(a, b, c, d, e, f); } + public static Affine identity() { return new Affine(1, 0, 0, 1, 0, 0); } + public static Affine scale(float sx, float sy) { return new Affine(sx, 0, 0, sy, 0, 0); } + public static Affine shear(float degrees) { + return new Affine(1, 0, (float)Math.tan(degrees * (float)(Math.PI / 180.0)), 1, 0, 0); } + public static Affine translate(float tx, float ty) { return new Affine(1, 0, 0, 1, tx, ty); } + public static Affine flip(boolean horiz, boolean vert) { return new Affine(horiz ? -1 : 1, 0, 0, vert ? -1 : 1, 0, 0); } + public float multiply_px(float x, float y) { return x * a + y * c + e; } + public float multiply_py(float x, float y) { return x * b + y * d + f; } + + public static Affine rotate(float degrees) { + float s = (float)Math.sin(degrees * (float)(Math.PI / 180.0)); + float c = (float)Math.cos(degrees * (float)(Math.PI / 180.0)); + return new Affine(c, s, -s, c, 0, 0); + } + + / ** this = this * a * / + public Affine multiply(Affine A) { + float _a = this.a * A.a + this.b * A.c; + float _b = this.a * A.b + this.b * A.d; + float _c = this.c * A.a + this.d * A.c; + float _d = this.c * A.b + this.d * A.d; + float _e = this.e * A.a + this.f * A.c + A.e; + float _f = this.e * A.b + this.f * A.d + A.f; + a = _a; b = _b; c = _c; d = _d; e = _e; f = _f; + return this; + } + + public void invert() { + float det = 1 / (a * d - b * c); + float _a = d * det; + float _b = -1 * b * det; + float _c = -1 * c * det; + float _d = a * det; + float _e = -1 * e * a - f * c; + float _f = -1 * e * b - f * d; + a = _a; b = _b; c = _c; d = _d; e = _e; f = _f; + } + } + + + // PathTokenizer ////////////////////////////////////////////////////////////////////////////// + + public static final float PX_PER_INCH = 72; + public static final float INCHES_PER_CM = (float)0.3937; + public static final float INCHES_PER_MM = INCHES_PER_CM / 10; + + public static class PathTokenizer { + // FIXME: check array bounds exception for improperly terminated string + String s; + int i = 0; + char lastCommand = 'M'; + public PathTokenizer(String s) { this.s = s; } + private void consumeWhitespace() { + while(i < s.length() && (Character.isWhitespace(s.charAt(i)))) i++; + if (i < s.length() && s.charAt(i) == ',') i++; + while(i < s.length() && (Character.isWhitespace(s.charAt(i)))) i++; + } + public boolean hasMoreTokens() { consumeWhitespace(); return i < s.length(); } + public char parseCommand() { + consumeWhitespace(); + char c = s.charAt(i); + if (!Character.isLetter(c)) return lastCommand; + i++; + return lastCommand = c; + } + public float parseFloat() { + consumeWhitespace(); + int start = i; + float multiplier = 1; + for(; i < s.length(); i++) { + char c = s.charAt(i); + if (Character.isWhitespace(c) || c == ',' || (c == '-' && i != start)) break; + if (!((c >= '0' && c <= '9') || c == '.' || c == 'e' || c == 'E' || c == '-')) { + if (c == '%') { // FIXME + } else if (s.regionMatches(i, "pt", 0, i+2)) { // FIXME + } else if (s.regionMatches(i, "em", 0, i+2)) { // FIXME + } else if (s.regionMatches(i, "pc", 0, i+2)) { // FIXME + } else if (s.regionMatches(i, "ex", 0, i+2)) { // FIXME + } else if (s.regionMatches(i, "mm", 0, i+2)) { i += 2; multiplier = INCHES_PER_MM * PX_PER_INCH; break; + } else if (s.regionMatches(i, "cm", 0, i+2)) { i += 2; multiplier = INCHES_PER_CM * PX_PER_INCH; break; + } else if (s.regionMatches(i, "in", 0, i+2)) { i += 2; multiplier = PX_PER_INCH; break; + } else if (s.regionMatches(i, "px", 0, i+2)) { i += 2; break; + } else if (Character.isLetter(c)) break; + throw new RuntimeException("didn't expect character \"" + c + "\" in a numeric constant"); + } + } + if (start == i) throw new RuntimeException("FIXME"); + return Float.parseFloat(s.substring(start, i)) * multiplier; + } + } + + + // Abstract Path ////////////////////////////////////////////////////////////////////////////// + + / ** an abstract path; may contain splines and arcs * / + public static class VectorPath { + + // the number of vertices on this path + int numvertices = 0; + + // the vertices of the path + float[] x = new float[DEFAULT_PATHLEN]; + float[] y = new float[DEFAULT_PATHLEN]; + + // the type of each edge; type[i] is the type of the edge from x[i],y[i] to x[i+1],y[i+1] + byte[] type = new byte[DEFAULT_PATHLEN]; + + // bezier control points + float[] c1x = new float[DEFAULT_PATHLEN]; // or rx (arcto) + float[] c1y = new float[DEFAULT_PATHLEN]; // or ry (arcto) + float[] c2x = new float[DEFAULT_PATHLEN]; // or x-axis-rotation (arcto) + float[] c2y = new float[DEFAULT_PATHLEN]; // or large-arc << 1 | sweep (arcto) + + boolean closed = false; + + static final byte TYPE_MOVETO = 0; + static final byte TYPE_LINETO = 1; + static final byte TYPE_ARCTO = 2; + static final byte TYPE_CUBIC = 3; + static final byte TYPE_QUADRADIC = 4; + + / ** Creates a concrete vector path transformed through the given matrix. * / + public RasterPath realize(Affine a) { + + RasterPath ret = new RasterPath(); + int NUMSTEPS = 5; // FIXME + ret.numvertices = 1; + ret.x[0] = (int)Math.round(a.multiply_px(x[0], y[0])); + ret.y[0] = (int)Math.round(a.multiply_py(x[0], y[0])); + + for(int i=1; i> 1; + float fs = ((int)c2y[i]) & 1; + float x1 = x[i]; + float y1 = y[i]; + float x2 = x[i+1]; + float y2 = y[i+1]; + + // F.6.5: given x1,y1,x2,y2,fa,fs, compute cx,cy,theta1,dtheta + float x1_ = (float)Math.cos(phi) * (x1 - x2) / 2 + (float)Math.sin(phi) * (y1 - y2) / 2; + float y1_ = -1 * (float)Math.sin(phi) * (x1 - x2) / 2 + (float)Math.cos(phi) * (y1 - y2) / 2; + float tmp = (float)Math.sqrt((rx * rx * ry * ry - rx * rx * y1_ * y1_ - ry * ry * x1_ * x1_) / + (rx * rx * y1_ * y1_ + ry * ry * x1_ * x1_)); + float cx_ = (fa == fs ? -1 : 1) * tmp * (rx * y1_ / ry); + float cy_ = (fa == fs ? -1 : 1) * -1 * tmp * (ry * x1_ / rx); + float cx = (float)Math.cos(phi) * cx_ - (float)Math.sin(phi) * cy_ + (x1 + x2) / 2; + float cy = (float)Math.sin(phi) * cx_ + (float)Math.cos(phi) * cy_ + (y1 + y2) / 2; + + // F.6.4 Conversion from center to endpoint parameterization + float ux = 1, uy = 0, vx = (x1_ - cx_) / rx, vy = (y1_ - cy_) / ry; + float det = ux * vy - uy * vx; + float theta1 = (det < 0 ? -1 : 1) * + (float)Math.acos((ux * vx + uy * vy) / + ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy))); + ux = (x1_ - cx_) / rx; uy = (y1_ - cy_) / ry; + vx = (-1 * x1_ - cx_) / rx; vy = (-1 * y1_ - cy_) / ry; + det = ux * vy - uy * vx; + float dtheta = (det < 0 ? -1 : 1) * + (float)Math.acos((ux * vx + uy * vy) / + ((float)Math.sqrt(ux * ux + uy * uy) * (float)Math.sqrt(vx * vx + vy * vy))); + dtheta = dtheta % (float)(2 * Math.PI); + + if (fs == 0 && dtheta > 0) theta1 -= 2 * PI; + if (fs == 1 && dtheta < 0) theta1 += 2 * PI; + + if (fa == 1 && dtheta < 0) dtheta = 2 * PI + dtheta; + else if (fa == 1 && dtheta > 0) dtheta = -1 * (2 * PI - dtheta); + + // FIXME: integrate F.6.6 + // FIXME: isn't quite ending where it should... + + // F.6.3: Parameterization alternatives + float theta = theta1; + for(int j=0; j 0) ret.sort(0, ret.numedges - 1, false); + return ret; + } + + protected void parseSingleCommandAndArguments(PathTokenizer t, char command, boolean relative) { + if (numvertices == 0 && command != 'm') throw new RuntimeException("first command MUST be an 'm'"); + if (numvertices > x.length - 2) { + float[] new_x = new float[x.length * 2]; System.arraycopy(x, 0, new_x, 0, x.length); x = new_x; + float[] new_y = new float[y.length * 2]; System.arraycopy(y, 0, new_y, 0, y.length); y = new_y; + } + switch(command) { + case 'z': { + int where; + type[numvertices-1] = TYPE_LINETO; + for(where = numvertices - 1; where > 0; where--) + if (type[where - 1] == TYPE_MOVETO) break; + x[numvertices] = x[where]; + y[numvertices] = y[where]; + numvertices++; + closed = true; + break; + } + + case 'm': { + if (numvertices > 0) type[numvertices-1] = TYPE_MOVETO; + x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + numvertices++; + break; + } + + case 'l': case 'h': case 'v': { + type[numvertices-1] = TYPE_LINETO; + float first = t.parseFloat(), second; + if (command == 'h') { + second = relative ? 0 : y[numvertices - 1]; + } else if (command == 'v') { + second = first; first = relative ? 0 : x[numvertices - 1]; + } else { + second = t.parseFloat(); + } + x[numvertices] = first + (relative ? x[numvertices - 1] : 0); + y[numvertices] = second + (relative ? y[numvertices - 1] : 0); + numvertices++; + break; + } + + case 'a': { + type[numvertices-1] = TYPE_ARCTO; + c1x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + c1y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + c2x[numvertices-1] = (t.parseFloat() / 360) * 2 * PI; + c2y[numvertices-1] = (((int)t.parseFloat()) << 1) | (int)t.parseFloat(); + x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + numvertices++; + break; + } + + case 's': case 'c': { + type[numvertices-1] = TYPE_CUBIC; + if (command == 'c') { + c1x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + c1y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + } else if (numvertices > 1 && type[numvertices-2] == TYPE_CUBIC) { + c1x[numvertices-1] = 2 * x[numvertices - 1] - c2x[numvertices-2]; + c1y[numvertices-1] = 2 * y[numvertices - 1] - c2y[numvertices-2]; + } else { + c1x[numvertices-1] = x[numvertices-1]; + c1y[numvertices-1] = y[numvertices-1]; + } + c2x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + c2y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + numvertices++; + break; + } + + case 't': case 'q': { + type[numvertices-1] = TYPE_QUADRADIC; + if (command == 'q') { + c1x[numvertices-1] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + c1y[numvertices-1] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + } else if (numvertices > 1 && type[numvertices-2] == TYPE_QUADRADIC) { + c1x[numvertices-1] = 2 * x[numvertices - 1] - c1x[numvertices-2]; + c1y[numvertices-1] = 2 * y[numvertices - 1] - c1y[numvertices-2]; + } else { + c1x[numvertices-1] = x[numvertices-1]; + c1y[numvertices-1] = y[numvertices-1]; + } + x[numvertices] = t.parseFloat() + (relative ? x[numvertices - 1] : 0); + y[numvertices] = t.parseFloat() + (relative ? y[numvertices - 1] : 0); + numvertices++; + break; + } + + default: + // FIXME + } + / * + // invariant: after this loop, no two lines intersect other than at a vertex + // FIXME: cleanup + int index = numvertices - 2; + for(int i=0; i Math.min(x[i+1], x[i]) && _x < Math.max(x[i+1], x[i]) && + _x > Math.min(x[j+1], x[j]) && _x < Math.max(x[j+1], x[j])) { + // FIXME: something's not right in here. See if we can do without fracturing line 'i'. + for(int k = ++numvertices; k>i; k--) { x[k] = x[k - 1]; y[k] = y[k - 1]; } + x[i+1] = _x; + y[i+1] = _y; + x[numvertices] = x[numvertices - 1]; x[numvertices - 1] = _x; + y[numvertices] = y[numvertices - 1]; y[numvertices - 1] = _y; + edges[numedges++] = numvertices - 1; numvertices++; + index++; + break; // actually 'continue' the outermost loop + } + } + } + * / + + } + } + + + + + // Concrete Vector Path ////////////////////////////////////////////////////////////////////////////// + + / ** a vector path * / + public static class RasterPath { + + // the vertices of this path + int[] x = new int[DEFAULT_PATHLEN]; + int[] y = new int[DEFAULT_PATHLEN]; + int numvertices = 0; + + / ** + * A list of the vertices on this path which *start* an edge (rather than a moveto), sorted by increasing y. + * example: x[edges[1]],y[edges[1]] - x[edges[i]+1],y[edges[i]+1] is the second-topmost edge + * note that if x[i],y[i] - x[i+1],y[i+1] is a MOVETO, then no element in edges will be equal to i + * / + int[] edges = new int[DEFAULT_PATHLEN]; + int numedges = 0; + + / ** FIXME: if a path is closed "manually" you get caps on the ends; otherwise you get a marker... * / + boolean closed = false; + + / ** simple quicksort, from http://sourceforge.net/snippet/detail.php?type=snippet&id=100240 * / + int sort(int left, int right, boolean partition) { + if (partition) { + int i, j, middle; + middle = (left + right) / 2; + int s = edges[right]; edges[right] = edges[middle]; edges[middle] = s; + for (i = left - 1, j = right; ; ) { + while (y[edges[++i]] < y[edges[right]]); + while (j > left && y[edges[--j]] > y[edges[right]]); + if (i >= j) break; + s = edges[i]; edges[i] = edges[j]; edges[j] = s; + } + s = edges[right]; edges[right] = edges[i]; edges[i] = s; + return i; + } else { + if (left >= right) return 0; + int p = sort(left, right, true); + sort(left, p - 1, false); + sort(p + 1, right, false); + return 0; + } + } + + / ** finds the x value at which the line intercepts the line y=_y * / + private int intercept(int i, float _y, boolean includeTop, boolean includeBottom) { + if (includeTop ? (_y < Math.min(y[i], y[i+1])) : (_y <= Math.min(y[i], y[i+1]))) + return Integer.MIN_VALUE; + if (includeBottom ? (_y > Math.max(y[i], y[i+1])) : (_y >= Math.max(y[i], y[i+1]))) + return Integer.MIN_VALUE; + return (int)Math.round((((float)(x[i + 1] - x[i])) / + ((float)(y[i + 1] - y[i])) ) * ((float)(_y - y[i])) + x[i]); + } + + / ** fill the interior of the path * / + public void fill(DoubleBuffer buf, RasterPath pen, Paint paint) { + if (numedges == 0) return; + int y0 = y[edges[0]], y1 = y0; + boolean useEvenOdd = false; + + // we iterate over all endpoints in increasing y-coordinate order + for(int index = 1; index x1) continue; + if (midpoint == x1 && i >= rightSegment) continue; + rightSegment = i; + x1 = midpoint; + } + if (leftSegment == rightSegment || rightSegment == Integer.MAX_VALUE) break; + if (leftSegment != -1) + if ((useEvenOdd && count % 2 != 0) || (!useEvenOdd && count != 0)) + paint.fillTrapezoid(intercept(edges[leftSegment], y0, true, true), + intercept(edges[rightSegment], y0, true, true), y0, + intercept(edges[leftSegment], y1, true, true), + intercept(edges[rightSegment], y1, true, true), y1, + buf); + if (useEvenOdd) count++; + else count += (y[edges[rightSegment]] < y[edges[rightSegment]+1]) ? -1 : 1; + leftSegment = rightSegment; x0 = x1; + } + } + } + + / ** stroke the outline of the path * / + public void stroke(DoubleBuffer buf, int width, int color, boolean mitre, + String dashArray, int dashOffset, float segLength) { + if (dashArray != null) { + float ratio = 1; + if (segLength > 0) { + float actualLength = 0; + for(int i=0; i _x2) { float _x0 = _x1; _x1 = _x2; _x2 = _x0; } + + for(float x=_x1; x<_x2; x++) { + + float distance = isLinear ? + // length of projection of onto the gradient vector == { \dot {grad \over |grad|}} + (x * (x2 - x1) + y * (y2 - y1)) / (float)Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)) : + + // radial form is simple! FIXME, not quite right + (float)Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); + + // FIXME: offsets are 0..1, not 0..length(gradient) + int i = 0; for(; i= stop_offsets.length) continue; + + // gradate from offsets[i - 1] to offsets[i] + float percentage = ((distance - stop_offsets[i - 1]) / (stop_offsets[i] - stop_offsets[i - 1])); + + int a = (int)((((stop_colors[i] >> 24) & 0xff) - ((stop_colors[i - 1] >> 24) & 0xff)) * percentage) + + ((stop_colors[i - 1] >> 24) & 0xff); + int r = (int)((((stop_colors[i] >> 16) & 0xff) - ((stop_colors[i - 1] >> 16) & 0xff)) * percentage) + + ((stop_colors[i - 1] >> 16) & 0xff); + int g = (int)((((stop_colors[i] >> 8) & 0xff) - ((stop_colors[i - 1] >> 8) & 0xff)) * percentage) + + ((stop_colors[i - 1] >> 8) & 0xff); + int b = (int)((((stop_colors[i] >> 0) & 0xff) - ((stop_colors[i - 1] >> 0) & 0xff)) * percentage) + + ((stop_colors[i - 1] >> 0) & 0xff); + int argb = (a << 24) | (r << 16) | (g << 8) | b; + buf.drawPoint((int)x, (int)Math.floor(y), argb); + } + } + } + } + + public static class LinearGradientPaint extends GradientPaint { + public LinearGradientPaint(float x1, float y1, float x2, float y2, boolean reflect, boolean repeat, + Affine gradientTransform, int[] stop_colors, float[] stop_offsets) { + super(reflect, repeat, gradientTransform, stop_colors, stop_offsets); + this.x1 = x1; this.x2 = x2; this.y1 = y1; this.y2 = y2; + } + float x1 = 0, y1 = 0, x2 = 300, y2 = 300; + } + + public static class RadialGradientPaint extends GradientPaint { + public RadialGradientPaint(float cx, float cy, float fx, float fy, float r, boolean reflect, boolean repeat, + Affine gradientTransform, int[] stop_colors, float[] stop_offsets) { + super(reflect, repeat, gradientTransform, stop_colors, stop_offsets); + this.cx = cx; this.cy = cy; this.fx = fx; this.fy = fy; this.r = r; + } + + float cx, cy, r, fx, fy; + + } + * / + + // Private Constants ////////////////////////////////////////////////////////////////////////////////// + + private static final int DEFAULT_PATHLEN = 1000; + + / ** Copied verbatim from the SVG specification * / + public static Hashtable colors = new Hashtable(400); + static { + colors.put("aliceblue", new Integer((240 << 16) | (248 << 8) | 255)); + colors.put("antiquewhite", new Integer((250 << 16) | (235 << 8) | 215)); + colors.put("aqua", new Integer((0 << 16) | (255 << 8) | 255)); + colors.put("aquamarine", new Integer((127 << 16) | (255 << 8) | 212)); + colors.put("azure", new Integer((240 << 16) | (255 << 8) | 255)); + colors.put("beige", new Integer((245 << 16) | (245 << 8) | 220)); + colors.put("bisque", new Integer((255 << 16) | (228 << 8) | 196)); + colors.put("black", new Integer((0 << 16) | (0 << 8) | 0)); + colors.put("blanchedalmond", new Integer((255 << 16) | (235 << 8) | 205)); + colors.put("blue", new Integer((0 << 16) | (0 << 8) | 255)); + colors.put("blueviolet", new Integer((138 << 16) | (43 << 8) | 226)); + colors.put("brown", new Integer((165 << 16) | (42 << 8) | 42)); + colors.put("burlywood", new Integer((222 << 16) | (184 << 8) | 135)); + colors.put("cadetblue", new Integer((95 << 16) | (158 << 8) | 160)); + colors.put("chartreuse", new Integer((127 << 16) | (255 << 8) | 0)); + colors.put("chocolate", new Integer((210 << 16) | (105 << 8) | 30)); + colors.put("coral", new Integer((255 << 16) | (127 << 8) | 80)); + colors.put("cornflowerblue", new Integer((100 << 16) | (149 << 8) | 237)); + colors.put("cornsilk", new Integer((255 << 16) | (248 << 8) | 220)); + colors.put("crimson", new Integer((220 << 16) | (20 << 8) | 60)); + colors.put("cyan", new Integer((0 << 16) | (255 << 8) | 255)); + colors.put("darkblue", new Integer((0 << 16) | (0 << 8) | 139)); + colors.put("darkcyan", new Integer((0 << 16) | (139 << 8) | 139)); + colors.put("darkgoldenrod", new Integer((184 << 16) | (134 << 8) | 11)); + colors.put("darkgray", new Integer((169 << 16) | (169 << 8) | 169)); + colors.put("darkgreen", new Integer((0 << 16) | (100 << 8) | 0)); + colors.put("darkgrey", new Integer((169 << 16) | (169 << 8) | 169)); + colors.put("darkkhaki", new Integer((189 << 16) | (183 << 8) | 107)); + colors.put("darkmagenta", new Integer((139 << 16) | (0 << 8) | 139)); + colors.put("darkolivegreen", new Integer((85 << 16) | (107 << 8) | 47)); + colors.put("darkorange", new Integer((255 << 16) | (140 << 8) | 0)); + colors.put("darkorchid", new Integer((153 << 16) | (50 << 8) | 204)); + colors.put("darkred", new Integer((139 << 16) | (0 << 8) | 0)); + colors.put("darksalmon", new Integer((233 << 16) | (150 << 8) | 122)); + colors.put("darkseagreen", new Integer((143 << 16) | (188 << 8) | 143)); + colors.put("darkslateblue", new Integer((72 << 16) | (61 << 8) | 139)); + colors.put("darkslategray", new Integer((47 << 16) | (79 << 8) | 79)); + colors.put("darkslategrey", new Integer((47 << 16) | (79 << 8) | 79)); + colors.put("darkturquoise", new Integer((0 << 16) | (206 << 8) | 209)); + colors.put("darkviolet", new Integer((148 << 16) | (0 << 8) | 211)); + colors.put("deeppink", new Integer((255 << 16) | (20 << 8) | 147)); + colors.put("deepskyblue", new Integer((0 << 16) | (191 << 8) | 255)); + colors.put("dimgray", new Integer((105 << 16) | (105 << 8) | 105)); + colors.put("dimgrey", new Integer((105 << 16) | (105 << 8) | 105)); + colors.put("dodgerblue", new Integer((30 << 16) | (144 << 8) | 255)); + colors.put("firebrick", new Integer((178 << 16) | (34 << 8) | 34)); + colors.put("floralwhite", new Integer((255 << 16) | (250 << 8) | 240)); + colors.put("forestgreen", new Integer((34 << 16) | (139 << 8) | 34)); + colors.put("fuchsia", new Integer((255 << 16) | (0 << 8) | 255)); + colors.put("gainsboro", new Integer((220 << 16) | (220 << 8) | 220)); + colors.put("ghostwhite", new Integer((248 << 16) | (248 << 8) | 255)); + colors.put("gold", new Integer((255 << 16) | (215 << 8) | 0)); + colors.put("goldenrod", new Integer((218 << 16) | (165 << 8) | 32)); + colors.put("gray", new Integer((128 << 16) | (128 << 8) | 128)); + colors.put("grey", new Integer((128 << 16) | (128 << 8) | 128)); + colors.put("green", new Integer((0 << 16) | (128 << 8) | 0)); + colors.put("greenyellow", new Integer((173 << 16) | (255 << 8) | 47)); + colors.put("honeydew", new Integer((240 << 16) | (255 << 8) | 240)); + colors.put("hotpink", new Integer((255 << 16) | (105 << 8) | 180)); + colors.put("indianred", new Integer((205 << 16) | (92 << 8) | 92)); + colors.put("indigo", new Integer((75 << 16) | (0 << 8) | 130)); + colors.put("ivory", new Integer((255 << 16) | (255 << 8) | 240)); + colors.put("khaki", new Integer((240 << 16) | (230 << 8) | 140)); + colors.put("lavender", new Integer((230 << 16) | (230 << 8) | 250)); + colors.put("lavenderblush", new Integer((255 << 16) | (240 << 8) | 245)); + colors.put("lawngreen", new Integer((124 << 16) | (252 << 8) | 0)); + colors.put("lemonchiffon", new Integer((255 << 16) | (250 << 8) | 205)); + colors.put("lightblue", new Integer((173 << 16) | (216 << 8) | 230)); + colors.put("lightcoral", new Integer((240 << 16) | (128 << 8) | 128)); + colors.put("lightcyan", new Integer((224 << 16) | (255 << 8) | 255)); + colors.put("lightgoldenrodyellow", new Integer((250 << 16) | (250 << 8) | 210)); + colors.put("lightgray", new Integer((211 << 16) | (211 << 8) | 211)); + colors.put("lightgreen", new Integer((144 << 16) | (238 << 8) | 144)); + colors.put("lightgrey", new Integer((211 << 16) | (211 << 8) | 211)); + colors.put("lightpink", new Integer((255 << 16) | (182 << 8) | 193)); + colors.put("lightsalmon", new Integer((255 << 16) | (160 << 8) | 122)); + colors.put("lightseagreen", new Integer((32 << 16) | (178 << 8) | 170)); + colors.put("lightskyblue", new Integer((135 << 16) | (206 << 8) | 250)); + colors.put("lightslategray", new Integer((119 << 16) | (136 << 8) | 153)); + colors.put("lightslategrey", new Integer((119 << 16) | (136 << 8) | 153)); + colors.put("lightsteelblue", new Integer((176 << 16) | (196 << 8) | 222)); + colors.put("lightyellow", new Integer((255 << 16) | (255 << 8) | 224)); + colors.put("lime", new Integer((0 << 16) | (255 << 8) | 0)); + colors.put("limegreen", new Integer((50 << 16) | (205 << 8) | 50)); + colors.put("linen", new Integer((250 << 16) | (240 << 8) | 230)); + colors.put("magenta", new Integer((255 << 16) | (0 << 8) | 255)); + colors.put("maroon", new Integer((128 << 16) | (0 << 8) | 0)); + colors.put("mediumaquamarine", new Integer((102 << 16) | (205 << 8) | 170)); + colors.put("mediumblue", new Integer((0 << 16) | (0 << 8) | 205)); + colors.put("mediumorchid", new Integer((186 << 16) | (85 << 8) | 211)); + colors.put("mediumpurple", new Integer((147 << 16) | (112 << 8) | 219)); + colors.put("mediumseagreen", new Integer((60 << 16) | (179 << 8) | 113)); + colors.put("mediumslateblue", new Integer((123 << 16) | (104 << 8) | 238)); + colors.put("mediumspringgreen", new Integer((0 << 16) | (250 << 8) | 154)); + colors.put("mediumturquoise", new Integer((72 << 16) | (209 << 8) | 204)); + colors.put("mediumvioletred", new Integer((199 << 16) | (21 << 8) | 133)); + colors.put("midnightblue", new Integer((25 << 16) | (25 << 8) | 112)); + colors.put("mintcream", new Integer((245 << 16) | (255 << 8) | 250)); + colors.put("mistyrose", new Integer((255 << 16) | (228 << 8) | 225)); + colors.put("moccasin", new Integer((255 << 16) | (228 << 8) | 181)); + colors.put("navajowhite", new Integer((255 << 16) | (222 << 8) | 173)); + colors.put("navy", new Integer((0 << 16) | (0 << 8) | 128)); + colors.put("oldlace", new Integer((253 << 16) | (245 << 8) | 230)); + colors.put("olive", new Integer((128 << 16) | (128 << 8) | 0)); + colors.put("olivedrab", new Integer((107 << 16) | (142 << 8) | 35)); + colors.put("orange", new Integer((255 << 16) | (165 << 8) | 0)); + colors.put("orangered", new Integer((255 << 16) | (69 << 8) | 0)); + colors.put("orchid", new Integer((218 << 16) | (112 << 8) | 214)); + colors.put("palegoldenrod", new Integer((238 << 16) | (232 << 8) | 170)); + colors.put("palegreen", new Integer((152 << 16) | (251 << 8) | 152)); + colors.put("paleturquoise", new Integer((175 << 16) | (238 << 8) | 238)); + colors.put("palevioletred", new Integer((219 << 16) | (112 << 8) | 147)); + colors.put("papayawhip", new Integer((255 << 16) | (239 << 8) | 213)); + colors.put("peachpuff", new Integer((255 << 16) | (218 << 8) | 185)); + colors.put("peru", new Integer((205 << 16) | (133 << 8) | 63)); + colors.put("pink", new Integer((255 << 16) | (192 << 8) | 203)); + colors.put("plum", new Integer((221 << 16) | (160 << 8) | 221)); + colors.put("powderblue", new Integer((176 << 16) | (224 << 8) | 230)); + colors.put("purple", new Integer((128 << 16) | (0 << 8) | 128)); + colors.put("red", new Integer((255 << 16) | (0 << 8) | 0)); + colors.put("rosybrown", new Integer((188 << 16) | (143 << 8) | 143)); + colors.put("royalblue", new Integer((65 << 16) | (105 << 8) | 225)); + colors.put("saddlebrown", new Integer((139 << 16) | (69 << 8) | 19)); + colors.put("salmon", new Integer((250 << 16) | (128 << 8) | 114)); + colors.put("sandybrown", new Integer((244 << 16) | (164 << 8) | 96)); + colors.put("seagreen", new Integer((46 << 16) | (139 << 8) | 87)); + colors.put("seashell", new Integer((255 << 16) | (245 << 8) | 238)); + colors.put("sienna", new Integer((160 << 16) | (82 << 8) | 45)); + colors.put("silver", new Integer((192 << 16) | (192 << 8) | 192)); + colors.put("skyblue", new Integer((135 << 16) | (206 << 8) | 235)); + colors.put("slateblue", new Integer((106 << 16) | (90 << 8) | 205)); + colors.put("slategray", new Integer((112 << 16) | (128 << 8) | 144)); + colors.put("slategrey", new Integer((112 << 16) | (128 << 8) | 144)); + colors.put("snow", new Integer((255 << 16) | (250 << 8) | 250)); + colors.put("springgreen", new Integer((0 << 16) | (255 << 8) | 127)); + colors.put("steelblue", new Integer((70 << 16) | (130 << 8) | 180)); + colors.put("tan", new Integer((210 << 16) | (180 << 8) | 140)); + colors.put("teal", new Integer((0 << 16) | (128 << 8) | 128)); + colors.put("thistle", new Integer((216 << 16) | (191 << 8) | 216)); + colors.put("tomato", new Integer((255 << 16) | (99 << 8) | 71)); + colors.put("turquoise", new Integer((64 << 16) | (224 << 8) | 208)); + colors.put("violet", new Integer((238 << 16) | (130 << 8) | 238)); + colors.put("wheat", new Integer((245 << 16) | (222 << 8) | 179)); + colors.put("white", new Integer((255 << 16) | (255 << 8) | 255)); + colors.put("whitesmoke", new Integer((245 << 16) | (245 << 8) | 245)); + colors.put("yellow", new Integer((255 << 16) | (255 << 8) | 0)); + colors.put("yellowgreen", new Integer((154 << 16) | (205 << 8) | 50)); + } + + private static final float PI = (float)Math.PI; + */ +} diff --git a/src/org/xwt/XMLRPC.java b/src/org/xwt/XMLRPC.java index 7cef4c2..f11413c 100644 --- a/src/org/xwt/XMLRPC.java +++ b/src/org/xwt/XMLRPC.java @@ -103,9 +103,12 @@ class XMLRPC extends JS.Callable { else if (c.localName.equals("double")) objects.setElementAt(new Double(new String(content.getBuf(), 0, content.size())), objects.size() - 1); + // FIXME + /* else if (c.localName.equals("base64")) objects.setElementAt(new ByteStream(Base64.decode(new String(content.getBuf(), 0, content.size()))), objects.size() - 1); - + */ + else if (c.localName.equals("name")) objects.addElement(new String(content.getBuf(), 0, content.size())); @@ -196,6 +199,8 @@ class XMLRPC extends JS.Callable { sb.append(((Boolean)o).booleanValue() ? "1" : "0"); sb.append("\n"); + //FIXME + /* } else if (o instanceof ByteStream) { try { sb.append(" \n"); @@ -219,6 +224,7 @@ class XMLRPC extends JS.Callable { if (Log.on) Log.log(this, e); throw new JS.Exn("caught IOException while attempting to send a ByteStream via XML-RPC"); } + */ } else if (o instanceof String) { sb.append(" "); diff --git a/src/org/xwt/XWT.java b/src/org/xwt/XWT.java index 8efbc2c..0329a60 100644 --- a/src/org/xwt/XWT.java +++ b/src/org/xwt/XWT.java @@ -39,8 +39,8 @@ public final class XWT extends JS.Obj { else if (name.equals("clipboard")) Platform.setClipBoard(value.toString()); else if (name.equals("proxyAuthorization")) { // FIXME: undocumented, possibly insecure - Proxy.Authorization.authorization = value.toString(); - Proxy.Authorization.waitingForUser.release(); + HTTP.Proxy.Authorization.authorization = value.toString(); + HTTP.Proxy.Authorization.waitingForUser.release(); } else super.put(name, value); } @@ -71,7 +71,7 @@ public final class XWT extends JS.Obj { }}); super.put("load", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn { - return Res.stringToResource(args.elementAt(0).toString()); + return Res.stringToRes(args.elementAt(0).toString()); }}); super.put("theme", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn { @@ -173,6 +173,7 @@ public final class XWT extends JS.Obj { return null; }}); + /* FIXME super.put("openFile", new JS.Callable() { public Object call(JS.Array args) throws JS.Exn { if (args.length() != 1) return null; String file = Platform.fileDialog(args.elementAt(0).toString(), false); @@ -235,7 +236,7 @@ public final class XWT extends JS.Obj { } } }); - + */ super.put("recursivePrintObject", new JS.Callable() { public Object call(JS.Array args) { if (args.length() != 1) return null; recurse("", "", args.elementAt(0)); diff --git a/src/org/xwt/plat/AWT.java b/src/org/xwt/plat/AWT.java index 6e01352..c7888a0 100644 --- a/src/org/xwt/plat/AWT.java +++ b/src/org/xwt/plat/AWT.java @@ -15,7 +15,7 @@ import java.awt.event.*; public class AWT extends JVM { protected String getDescriptiveName() { return "Generic JDK 1.1+ with AWT"; } - protected PixelBuffer _createDoubleBuffer(int w, int h, Surface owner) { return new AWTDoubleBuffer(w, h); } + protected PixelBuffer _createPixelBuffer(int w, int h, Surface owner) { return new AWTPixelBuffer(w, h); } protected Picture _createPicture(int[] b, int w, int h) { return new AWTPicture(b, w, h); } protected int _getScreenWidth() { return Toolkit.getDefaultToolkit().getScreenSize().width; } protected int _getScreenHeight() { return Toolkit.getDefaultToolkit().getScreenSize().height; } @@ -137,7 +137,7 @@ public class AWT extends JVM { } } - protected static class AWTPixelBuffer extends DoubleBuffer { + protected static class AWTPixelBuffer extends PixelBuffer { protected Image i = null; protected Graphics g = null;