2003/02/22 03:55:06
authormegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:51:53 +0000 (06:51 +0000)
committermegacz <megacz@xwt.org>
Fri, 30 Jan 2004 06:51:53 +0000 (06:51 +0000)
darcs-hash:20040130065153-2ba56-0ecfac23c6ce85eb23576b507f713eb9845198ed.gz

README
src/org/xwt/Box.java
src/org/xwt/DoubleBuffer.java
src/org/xwt/HTTP.java
src/org/xwt/Main.java

diff --git a/README b/README
index 7dd22b1..a5348eb 100644 (file)
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 ==============================================================================
 XWT README
 ==============================================================================
 XWT README
-                  
+                   
 ______________________________________________________________________________
 Documentation
 
 ______________________________________________________________________________
 Documentation
 
index 4cefc9e..17283f6 100644 (file)
@@ -257,6 +257,15 @@ public final class Box extends JSObject {
     public Hash traps = null;
 
 
     public Hash traps = null;
 
 
+    // Vector Support /////////////////////////////////////////////////////////////////////
+
+    /** The SVG path for this node */
+    public String path = null;
+
+    /** The affine multiplied by the CTM *before* this element and its children are processed */
+    public SVG.Affine transform = null;
+
+
     // Instance Data: IndexOf  ////////////////////////////////////////////////////////////
 
     /** The indexof() Function; created lazily */
     // Instance Data: IndexOf  ////////////////////////////////////////////////////////////
 
     /** The indexof() Function; created lazily */
@@ -858,7 +867,8 @@ public final class Box extends JSObject {
     // Rendering Pipeline /////////////////////////////////////////////////////////////////////
 
     /** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */
     // Rendering Pipeline /////////////////////////////////////////////////////////////////////
 
     /** Renders self and children within the specified region. All rendering operations are clipped to xIn,yIn,wIn,hIn */
-    void render(int xIn, int yIn, int wIn, int hIn, DoubleBuffer buf) {
+    void render(int xIn, int yIn, int wIn, int hIn, DoubleBuffer buf) { render(xIn, yIn, wIn, hIn, buf, null); }
+    void render(int xIn, int yIn, int wIn, int hIn, DoubleBuffer buf, SVG.Affine ctm) {
         if (surface.abort || invisible) return;
 
         // intersect the x,y,w,h rendering window with ourselves; quit if it's empty
         if (surface.abort || invisible) return;
 
         // intersect the x,y,w,h rendering window with ourselves; quit if it's empty
@@ -885,6 +895,24 @@ public final class Box extends JSObject {
             else renderStretchedImage(x, y, w, h, buf);
         }
 
             else renderStretchedImage(x, y, w, h, buf);
         }
 
+       // FIXME: this should go at the top of this method
+       SVG.Affine ctm_;
+       if (transform != null) {
+           if (ctm == null) ctm = SVG.Affine.identity();
+           ctm_ = ctm.copy();
+           ctm_.multiply(transform);
+       } else {
+           ctm_ = ctm;
+       }
+
+       if (path != null) {
+           SVG.VP vp = SVG.VP.fromString(path);
+           if (ctm_ != null) vp.multiply(ctm_);
+           vp.sort();
+           vp.fill(buf, null, 0xFFFF0000, null);
+           vp.stroke(buf, 100, textcolor, false);
+       }
+
         if (text != null && !text.equals("")) renderText(x, y, w, h, buf);
 
         // now subtract the pad region from the clip region before proceeding
         if (text != null && !text.equals("")) renderText(x, y, w, h, buf);
 
         // now subtract the pad region from the clip region before proceeding
@@ -894,7 +922,7 @@ public final class Box extends JSObject {
         int h2 = min(y + h, pos(1) + size(1) - pad(1)) - y2;
 
         for(Box b = getChild(0); b != null; b = b.nextSibling())
         int h2 = min(y + h, pos(1) + size(1) - pad(1)) - y2;
 
         for(Box b = getChild(0); b != null; b = b.nextSibling())
-            b.render(x2, y2, w2, h2, buf);   
+            b.render(x2, y2, w2, h2, buf, ctm_);
     }
 
     private void renderBorder(int x, int y, int w, int h, DoubleBuffer buf) {
     }
 
     private void renderBorder(int x, int y, int w, int h, DoubleBuffer buf) {
index f420875..9e9d923 100644 (file)
@@ -9,10 +9,10 @@ package org.xwt;
  *  </p>
  *
  *  <p>
  *  </p>
  *
  *  <p>
- *  Implementations of the Platform class should return objects
- *  supporting this interface from the _createDoubleBuffer()
- *  method. These implementations may choose to use off-screen video
- *  ram for this purpose (for example, a Pixmap on X11).
+ *  Implementations of the Platform class should return subclasses of
+ *  DoubleBuffer from the _createDoubleBuffer() method. These
+ *  implementations may choose to use off-screen video ram for this
+ *  purpose (for example, a Pixmap on X11).
  *  </p>
  *
  *  <p>
  *  </p>
  *
  *  <p>
@@ -21,23 +21,206 @@ package org.xwt;
  *  represents regions internally as x,y,w,h.
  *  </p>
  */
  *  represents regions internally as x,y,w,h.
  *  </p>
  */
+
 public abstract class DoubleBuffer {
 
 public abstract class DoubleBuffer {
 
-    /** Draw the region of source within (sx1, sy1, sx2, sy2) onto the region of this DoubleBuffer within (dx1, dy1, dx2, dy2), scaling as needed. */
-    public abstract void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2);
+    // Methods to Be Overridden//////////////////////////////////////////////////////////////////////////////
 
 
-    /** Draw source onto this DoubleBuffer at (x,y) */
-    public abstract void drawPicture(Picture source, int x, int y);
+    /** Stretch the source image to (dx1, dy1, dx2, dy2), but clip it to (cx1, cy1, cx2, cy2) */
+    protected abstract void _drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int cx1, int cy1, int cx2, int cy2);
 
     /** Draw <tt>text</tt> in <tt>font</tt> and <tt>color</tt> on this DoubleBuffer, with the upper left corner of the text at (x, y) */
 
     /** Draw <tt>text</tt> in <tt>font</tt> and <tt>color</tt> on this DoubleBuffer, with the upper left corner of the text at (x, y) */
-    public abstract void drawString(String font, String text, int x, int y, int color);
+    protected abstract void _drawString(String font, String text, int x, int y, int color);
+
+    /** Draw a point at (x, y) */
+    protected void _drawPoint(int x, int y, int color) { fillRect(x, y, x + 1, y + 1, color); }
+
+    /** Draw a line from (x1, y1) to (x2, y2) that is width pixels wide */
+    protected void _drawLine(int x1, int y1, int x2, int y2, int width, int color) {
+       if (Math.abs(x1 - x2) < 1) {
+           for(int y=Math.min(y1, y2); y<Math.max(y1, y2); y++)
+               drawPoint(x1, y, color);
+           return;
+       }
+       if (Math.abs(y1 - y2) < 1) {
+           for(int x=Math.min(x1, x2); x<Math.max(x1, x2); x++)
+               drawPoint(x, y1, color);
+           return;
+       }
+       if (x1 > x2) {
+           int _x1 = x1; x1 = x2; x2 = _x1;
+           int _y1 = y1; y1 = y2; y2 = _y1;
+       }
+       double slope = (double)(y2 - y1) / (double)(x2 - x1);
+       int last_y = y1;
+       for(int x=x1; x<=x2; x++) {
+           int new_y = (int)(slope * (double)(x - x1)) + y1;
+           if (slope >= 0) {
+               for(int y=last_y + 1; y < new_y; y++) drawPoint(x, y, color);
+           } else {
+               for(int y=last_y - 1; y > new_y; y--) drawPoint(x, y, color);
+           }
+           if (x != x2) drawPoint(x, new_y, color);
+           last_y = new_y;
+       }
+    }
 
     /** Fill the region (x1, y1, x2, y2) with <tt>color</tt> (AARRGGBB format); the alpha channel component is ignored */
 
     /** Fill the region (x1, y1, x2, y2) with <tt>color</tt> (AARRGGBB format); the alpha channel component is ignored */
-    public abstract void fillRect(int x1, int y1, int x2, int y2, int color);
+    protected abstract void _fillRect(int x1, int y1, int x2, int y2, int color);
+
+    /** Fill in the trapezoid defined by (x1, y1), (x2, y1), (x3, y2), (x4, y2); leftSlope and rightSlope are provided for convenience */
+    protected void _fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, double leftSlope, double rightSlope, int color) {
+       for(int y=y1; y<y2; y++) {
+           int _x1 = (int)Math.floor((y - y1) * leftSlope + x1);
+           int _y1 = (int)Math.floor(y);
+           int _x2 = (int)Math.ceil((y - y1) * rightSlope + x2);
+           int _y2 = (int)Math.floor(y) + 1;
+           if (_x1 > _x2) { int _x0 = _x1; _x1 = _x2; _x2 = _x0; }
+           fillRect(_x1, _y1, _x2, _y2, color);
+       }
+    }
+
+
+    // Internal Stuff //////////////////////////////////////////////////////////////////////////////
+
+    protected int width, height;
+    private int clipx = 0, clipy = 0, clipw, cliph;
+    private DoubleBuffer() { }
+    protected DoubleBuffer(int width, int height) { this.width = width; this.height = height; clipw = width; cliph = height; }
+    protected SVG.Affine ctm = null;
+
+
+    // Final methods //////////////////////////////////////////////////////////////////////////////
+
+    public final int getHeight() { return width; }
+    public final int getWidth() { return height; }
+    public final void setTransform(SVG.Affine ctm) { this.ctm = ctm; }
+    public final void setClip(int x, int y, int x2, int y2) { clipx = x; clipy = y; clipw = x2 - x; cliph = y2 - y; }
+    public final void drawPicture(Picture p, int x, int y) { drawPicture(p, x, y, x + p.getWidth(), y + p.getHeight(), 0, 0, p.getWidth(), p.getHeight()); }
+
+    public final void drawPoint(int x, int y, int color) {
+       if (x > clipx && x < clipx + clipw && y > clipy && y < clipy + cliph)
+           _drawPoint(x, y, color);
+    }
+
+    public final void drawLine(int x1, int y1, int x2, int y2, int width, int color) {
+
+       if (x1 == x2 || y1 == y2) return;
+
+       // FIXME: don't compute slope if not needed
+       double slope = (y2 - y1) / (x2 - x1);
+       if (x1 < clipx) { y1 = (int)((clipx - x1) * slope + y1); x1 = clipx; }
+       if (y1 < clipy) { x1 = (int)((clipy - y1) / slope + x1); y1 = clipy; }
+       if (x2 > clipx + clipw) { x2 = clipx + clipw; y2 = (int)((x2 - x1) / slope + y1); }
+       if (y2 > clipy + cliph) { y2 = clipy + cliph; x2 = (int)((y2 - y1) * slope + y1); }
+
+       _drawLine(x1, y1, x2, y2, width, color);
+    }
+
+    /** Stretch the picture to fill (dx1, dy1, dx2, dy2) and blit it, clipping to (cx1, cy1, cx2, cy2) */
+    public final void drawPicture(Picture source, int dx1, int dy1, int dx2, int dy2, int cx1, int cy1, int cx2, int cy2) {
+
+       if (org.xwt.util.Log.assertionsEnabled) {
+           if (dx1 >= dx2) org.xwt.util.Log.log(DoubleBuffer.class, "drawPicture(): dx1 >= dx2: dx1=" + dx1 + " dx2=" + dx2, true);
+           if (dy1 >= dy2) org.xwt.util.Log.log(DoubleBuffer.class, "drawPicture(): dy1 >= dy2: dy1=" + dy1 + " dy2=" + dy2, true);
+           if (cx1 >= cx2) org.xwt.util.Log.log(DoubleBuffer.class, "drawPicture(): cx1 >= cx2: cx1=" + cx1 + " cx2=" + cx2, true);
+           if (cy1 >= cy2) org.xwt.util.Log.log(DoubleBuffer.class, "drawPicture(): cy1 >= cy2: cy1=" + cy1 + " cy2=" + cy2, true);
+       }
+
+       // shrink clipping rectangle to be no bigger than drawing rectangle
+       if (cx1 < dx1) cx1 = dx1;
+       if (cy1 < dy1) cy1 = dy1;
+       if (cx2 > dx2) cx2 = dx2;
+       if (cy2 > dy2) cy2 = dy2;
+
+       // intersect the two clipping regions
+       if (cx2 < clipx) return;
+       if (cy2 < clipy) return;
+       if (cx1 > clipx + clipw) return;
+       if (cy1 > clipy + cliph) return;
+       if (cx1 < clipx) cx1 = clipx;
+       if (cy1 < clipy) cy1 = clipy;
+       if (cx2 > clipx + clipw) cx2 = clipx + clipw;
+       if (cy2 > clipy + cliph) cy2 = clipy + cliph;
+    
+       if (ctm == null) {
+           _drawPicture(source, dx1, dy1, dx2, dy2, cx1, cy1, cx2, cy2);
+       } else {
+           _drawPicture(source,
+                        (int)ctm.multiply_px(dx1, dy1), (int)ctm.multiply_py(dx1, dy1), 
+                        (int)ctm.multiply_px(dx2, dy2), (int)ctm.multiply_py(dx2, dy2), 
+                        (int)ctm.multiply_px(cx1, cy1), (int)ctm.multiply_py(cx1, cy1), 
+                        (int)ctm.multiply_px(cx2, cy2), (int)ctm.multiply_py(cx2, cy2));
+       }
+    }
+
+    public final void drawString(String font, String text, int x, int y, int color) {
+       // FIXME: clipping
+       if (ctm == null) {
+           _drawString(font, text, x, y, color);
+       } else {
+           _drawString(font, text, (int)ctm.multiply_px(x, y), (int)ctm.multiply_py(x, y), color);
+       }
+    }
+
+    public final void fillRect(int x1, int y1, int x2, int y2, int color) {
+
+       x1 = Math.max(Math.min(clipx + clipw, x1), clipx);
+       x2 = Math.max(Math.min(clipx + clipw, x2), clipx);
+       y1 = Math.max(Math.min(clipy + cliph, y1), clipy);
+       y2 = Math.max(Math.min(clipy + cliph, y2), clipy);
+
+       if (ctm == null) {
+           _fillRect(x1, y1, x2, y2, color);
+       } else {
+           _fillRect((int)ctm.multiply_px(x1, y1), (int)ctm.multiply_py(x1, y1), 
+                     (int)ctm.multiply_px(x2, y2), (int)ctm.multiply_py(x2, y2), 
+                     color);
+       }
+    }
+
+    public final void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, int color) {
+       fillTrapezoid(x1, x2, y1, x3, x4, y2, (double)(x3 - x1) / (double)(y2 - y1), (double)(x4 - x2) / (double)(y2 - y1), color);
+    }
+
+    private final void fillTrapezoid(int x1, int x2, int y1, int x3, int x4, int y2, double slope1, double slope2, int color) {
+
+       // invariant: x1 <= x2, x3 <= x4, y1 <= y2
+       if (y1 == y2) return;
+       if (org.xwt.util.Log.assertionsEnabled) {
+           if (x1 > x2) org.xwt.util.Log.log(DoubleBuffer.class, "fillTrapezoid(): x1 > x2: x1=" + x1 + " x2=" + x2, true);
+           if (x3 > x4) org.xwt.util.Log.log(DoubleBuffer.class, "fillTrapezoid(): x3 > x4: x3=" + x3 + " x4=" + x4, true);
+           if (y1 >= y2) org.xwt.util.Log.log(DoubleBuffer.class, "fillTrapezoid(): y1 >= y2: y1=" + y1 + " y2=" + y2, true);
+       }
+
+       // clip top and bottom edges
+       if (y1 > clipy + cliph) return;
+       if (y2 < clipy) return;
+       if (y1 < clipy) { x1 = (int)(y1 + slope1 * clipy); x2 = (int)(y1 + slope2 * clipy); y1 = clipy; }
+       if (y2 > clipy + cliph) { y2 = clipy + cliph; x3 = (int)(y1 + slope1 * y2); x4 = (int)(slope2 * y2); }
+
+       if (x1 < clipx && x3 < clipx) {
+           x1 = x3 = clipx;
+       } else if (!(x1 >= clipx && x3 >= clipx)) {
+           int y = (int)((clipx - x1) / slope1 + y1);
+           int x = (int)(slope2 * (y - y2) + x2);
+           // we have to recurse here because we don't know which subtrapezoid might get split on the other side
+           fillTrapezoid(x1, x2, y1, clipx, x, y, slope1, slope2, color);
+           fillTrapezoid(clipx, x, y, x3, x4, y2, slope1, slope2, color);
+           return;
+       }
+
+       if (x2 >= clipx + clipw && x4 >= clipx + clipw) {
+           x2 = x4 = clipx + clipw;
+       } else if (!(x2 < clipx + clipw && x4 < clipx + clipw)) {
+           int y = (int)((clipx + clipw - x3) / slope2 + y1);
+           int x = (int)(slope1 * (y - y1) + x1);
+           _fillTrapezoid(x1, x2, y1, x, clipx + clipw, y, slope1, slope2, color);
+           _fillTrapezoid(x, clipx + clipw, y, x3, x4, y2, slope1, slope2, color);
+           return;
+       }
 
 
-    /** Sets the clip region for this DoubleBuffer to (x,y,x2,y2) */
-    public abstract void setClip(int x, int y, int x2, int y2);
+       _fillTrapezoid(x1, x2, y1, x3, x4, y2, slope1, slope2, color);
+    }
 
 
-    public abstract int getHeight();
-    public abstract int getWidth();
 }
 }
index 22a0761..acdfcc3 100644 (file)
@@ -39,6 +39,9 @@ public class HTTP {
     /** the socket's inputstream */
     InputStream in = null;
 
     /** the socket's inputstream */
     InputStream in = null;
 
+    /** the socket's outputstream */
+    PrintWriter out = null;
+
     /** the username and password portions of the URL */
     String userInfo = null;
 
     /** the username and password portions of the URL */
     String userInfo = null;
 
@@ -318,12 +321,24 @@ public class HTTP {
     // Everything Else ////////////////////////////////////////////////////////////////////////////
 
     private synchronized void connect() throws IOException {
     // Everything Else ////////////////////////////////////////////////////////////////////////////
 
     private synchronized void connect() throws IOException {
-        if (sock != null) {
+        if (sock != null && !"".equals(originalUrl)) {
             if (in == null) in = new BufferedInputStream(sock.getInputStream());
             return;
         }
         // grab the userinfo; gcj doesn't have java.net.URL.getUserInfo()
         String url = originalUrl;
             if (in == null) in = new BufferedInputStream(sock.getInputStream());
             return;
         }
         // grab the userinfo; gcj doesn't have java.net.URL.getUserInfo()
         String url = originalUrl;
+
+        if ("".equals(url)) {
+            userInfo = "";
+            this.url = null;
+            port = 80;
+            path = "/RPC2";
+            host = "";
+            in = System.in;
+            out = new PrintWriter(System.out);
+            return;
+        }
+
         userInfo = url.substring(url.indexOf("://") + 3);
         userInfo = userInfo.indexOf('/') == -1 ? userInfo : userInfo.substring(0, userInfo.indexOf('/'));
         if (userInfo.indexOf('@') != -1) {
         userInfo = url.substring(url.indexOf("://") + 3);
         userInfo = userInfo.indexOf('/') == -1 ? userInfo : userInfo.substring(0, userInfo.indexOf('/'));
         if (userInfo.indexOf('@') != -1) {
@@ -332,7 +347,7 @@ public class HTTP {
         } else {
             userInfo = null;
         }
         } else {
             userInfo = null;
         }
-
+        
         if (url.startsWith("https:")) {
             this.url = new URL("http" + url.substring(5));
             ssl = true;
         if (url.startsWith("https:")) {
             this.url = new URL("http" + url.substring(5));
             ssl = true;
@@ -341,6 +356,7 @@ public class HTTP {
         } else {
             this.url = new URL(url);
         }
         } else {
             this.url = new URL(url);
         }
+
         if (!skipResolveCheck) resolveAndCheckIfFirewalled(this.url.getHost());
         port = this.url.getPort();
         path = this.url.getFile();
         if (!skipResolveCheck) resolveAndCheckIfFirewalled(this.url.getHost());
         port = this.url.getPort();
         path = this.url.getFile();
@@ -356,11 +372,12 @@ public class HTTP {
         if (sock == null) sock = attemptDirect();
         if (sock == null) throw new HTTPException("unable to contact host " + host);
         if (in == null) in = new BufferedInputStream(sock.getInputStream());
         if (sock == null) sock = attemptDirect();
         if (sock == null) throw new HTTPException("unable to contact host " + host);
         if (in == null) in = new BufferedInputStream(sock.getInputStream());
+        if (out == null) out = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
     }
 
     public void sendRequest(String contentType, String content) throws IOException {
 
     }
 
     public void sendRequest(String contentType, String content) throws IOException {
 
-        PrintWriter pw = new PrintWriter(new OutputStreamWriter(sock.getOutputStream()));
+        PrintWriter pw = out;
         if (content != null) {
             pw.print("POST " + path + " HTTP/1.1\r\n");
         int contentLength = content.substring(0, 2).equals("\r\n") ?
         if (content != null) {
             pw.print("POST " + path + " HTTP/1.1\r\n");
         int contentLength = content.substring(0, 2).equals("\r\n") ?
index f6f9062..df1718a 100644 (file)
@@ -69,6 +69,7 @@ public class Main extends Applet {
                 }
                 else if (args[startargs].equals("-s")) showRenders = true;
                 else if (args[startargs].equals("-v")) Log.verbose = true;
                 }
                 else if (args[startargs].equals("-s")) showRenders = true;
                 else if (args[startargs].equals("-v")) Log.verbose = true;
+                else if (args[startargs].equals("-l")) Log.enableHTTP(args[++startargs]);
                 else break;
                 startargs++;
             }
                 else break;
                 startargs++;
             }