Back to index

wims  3.65+svn20090927
EPSGraphics.java
Go to the documentation of this file.
00001 /* Graphics class supporting EPS export from plots.
00002 
00003  Copyright (c) 1998-2006 The Regents of the University of California.
00004  All rights reserved.
00005  Permission is hereby granted, without written agreement and without
00006  license or royalty fees, to use, copy, modify, and distribute this
00007  software and its documentation for any purpose, provided that the above
00008  copyright notice and the following two paragraphs appear in all copies
00009  of this software.
00010 
00011  IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
00012  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
00013  ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
00014  THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
00015  SUCH DAMAGE.
00016 
00017  THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00018  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
00020  PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
00021  CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
00022  ENHANCEMENTS, OR MODIFICATIONS.
00023 
00024  PT_COPYRIGHT_VERSION_2
00025  COPYRIGHTENDKEY
00026  */
00027 package ptolemy.plot;
00028 
00029 import java.awt.Color;
00030 import java.awt.Font;
00031 import java.awt.FontMetrics;
00032 import java.awt.Graphics;
00033 import java.awt.Image;
00034 import java.awt.Point;
00035 import java.awt.Rectangle;
00036 import java.awt.Shape;
00037 import java.awt.Toolkit;
00038 import java.awt.datatransfer.Clipboard;
00039 import java.awt.datatransfer.StringSelection;
00040 import java.awt.image.ImageObserver;
00041 import java.io.BufferedOutputStream;
00042 import java.io.OutputStream;
00043 import java.io.PrintWriter;
00044 import java.util.Hashtable;
00045 
00046 import ptolemy.util.StringUtilities;
00047 
00050 
00067 public class EPSGraphics extends Graphics {
00077     public EPSGraphics(OutputStream out, int width, int height) {
00078         _width = width;
00079         _height = height;
00080         _out = out;
00081         _buffer.append("%!PS-Adobe-3.0 EPSF-3.0\n");
00082         _buffer.append("%%Creator: UC Berkeley Plot Package\n");
00083         _buffer.append("%%BoundingBox: 50 50 " + (50 + width) + " "
00084                 + (50 + height) + "\n");
00085         _buffer.append("%%Pages: 1\n");
00086         _buffer.append("%%Page: 1 1\n");
00087         _buffer.append("%%LanguageLevel: 2\n");
00088     }
00089 
00092     public void clearRect(int x, int y, int width, int height) {
00093     }
00094 
00095     public void clipRect(int x, int y, int width, int height) {
00096     }
00097 
00098     public void copyArea(int x, int y, int width, int height, int dx, int dy) {
00099     }
00100 
00101     public Graphics create() {
00102         return new EPSGraphics(_out, _width, _height);
00103     }
00104 
00105     public void dispose() {
00106     }
00107 
00108     public void drawArc(int x, int y, int width, int height, int startAngle,
00109             int arcAngle) {
00110     }
00111 
00112     public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
00113         return true;
00114     }
00115 
00116     public boolean drawImage(Image img, int x, int y, int width, int height,
00117             ImageObserver observer) {
00118         return true;
00119     }
00120 
00121     public boolean drawImage(Image img, int x, int y, Color bgcolor,
00122             ImageObserver observer) {
00123         return true;
00124     }
00125 
00126     public boolean drawImage(Image img, int x, int y, int width, int height,
00127             Color bgcolor, ImageObserver observer) {
00128         return true;
00129     }
00130 
00131     public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
00132             int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
00133         return true;
00134     }
00135 
00136     public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
00137             int sx1, int sy1, int sx2, int sy2, Color bgcolor,
00138             ImageObserver observer) {
00139         return true;
00140     }
00141 
00149     public void drawLine(int x1, int y1, int x2, int y2) {
00150         Point start = _convert(x1, y1);
00151         Point end = _convert(x2, y2);
00152         _buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
00153         _buffer.append("" + end.x + " " + end.y + " lineto\n");
00154         _buffer.append("stroke\n");
00155     }
00156 
00157     public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
00158     }
00159 
00169     public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
00170         if (!_polygon(xPoints, yPoints, nPoints)) {
00171             return;
00172         } else {
00173             _buffer.append("closepath stroke\n");
00174         }
00175     }
00176 
00184     // FIXME: Currently, this ignores the fourth argument and draws a circle
00185     // with diameter given by the third argument.
00186     public void drawOval(int x, int y, int width, int height) {
00187         int radius = width / 2;
00188         Point center = _convert(x + radius, y + radius);
00189         _buffer.append("newpath " + center.x + " " + center.y + " " + radius
00190                 + " 0 360 arc closepath stroke\n");
00191     }
00192 
00193     public void drawRect(int x, int y, int width, int height) {
00194         Point start = _convert(x, y);
00195         _buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
00196         _buffer.append("0 " + (-height) + " rlineto\n");
00197         _buffer.append("" + width + " 0 rlineto\n");
00198         _buffer.append("0 " + height + " rlineto\n");
00199         _buffer.append("" + (-width) + " 0 rlineto\n");
00200         _buffer.append("closepath stroke\n");
00201     }
00202 
00203     public void drawRoundRect(int x, int y, int width, int height,
00204             int arcWidth, int arcHeight) {
00205     }
00206 
00207     public void drawString(java.text.AttributedCharacterIterator iterator,
00208             int x, int y) {
00209         // FIXME: This method is present in the graphics class in JDK1.2,
00210         // but not in JDK1.1.
00211         throw new RuntimeException(
00212                 "Sorry, drawString(java.text.AttributedCharacterIterator, "
00213                         + "int , int) is not implemented in EPSGraphics");
00214     }
00215 
00222     public void drawString(String str, int x, int y) {
00223         Point start = _convert(x, y);
00224         _buffer.append("" + start.x + " " + start.y + " moveto\n");
00225 
00226         if ((str.indexOf("(") > -1) && (str.indexOf("\\(") == -1)) {
00227             str = StringUtilities.substitute(str, "(", "\\(");
00228         }
00229 
00230         if ((str.indexOf(")") > -1) && (str.indexOf("\\)") == -1)) {
00231             str = StringUtilities.substitute(str, ")", "\\)");
00232         }
00233 
00234         _buffer.append("(" + str + ") show\n");
00235     }
00236 
00237     public void fillArc(int x, int y, int width, int height, int startAngle,
00238             int arcAngle) {
00239     }
00240 
00250     public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
00251         if (!_polygon(xPoints, yPoints, nPoints)) {
00252             return;
00253         } else {
00254             _buffer.append("closepath fill\n");
00255         }
00256     }
00257 
00265     // FIXME: Currently, this ignores the fourth argument and draws a circle
00266     // with diameter given by the third argument.
00267     public void fillOval(int x, int y, int width, int height) {
00268         int radius = width / 2;
00269         Point center = _convert(x + radius, y + radius);
00270         _buffer.append("newpath " + center.x + " " + center.y + " " + radius
00271                 + " 0 360 arc closepath fill\n");
00272     }
00273 
00285     public void fillRect(int x, int y, int width, int height) {
00286         Point start = _convert(x, y);
00287         _fillPattern();
00288         _buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
00289         _buffer.append("0 " + (-height) + " rlineto\n");
00290         _buffer.append("" + width + " 0 rlineto\n");
00291         _buffer.append("0 " + height + " rlineto\n");
00292         _buffer.append("" + (-width) + " 0 rlineto\n");
00293         _buffer.append("closepath gsave fill grestore\n");
00294         _buffer.append("0.5 setlinewidth 0 setgray [] 0 setdash stroke\n");
00295 
00296         // reset the gray scale to black
00297         _buffer.append("1 setlinewidth\n");
00298     }
00299 
00300     public void fillRoundRect(int x, int y, int width, int height,
00301             int arcWidth, int arcHeight) {
00302     }
00303 
00304     public Shape getClip() {
00305         return null;
00306     }
00307 
00308     public Rectangle getClipBounds() {
00309         return null;
00310     }
00311 
00312     public Color getColor() {
00313         return _currentColor;
00314     }
00315 
00316     public Font getFont() {
00317         return _currentFont;
00318     }
00319 
00320     public FontMetrics getFontMetrics(Font f) {
00321         return null;
00322     }
00323 
00324     public void setFont(Font font) {
00325         if (font == null) {
00326             return;
00327         }
00328 
00329         int size = font.getSize();
00330         boolean bold = font.isBold();
00331 
00332         if (bold) {
00333             _buffer.append("/Helvetica-Bold findfont\n");
00334         } else {
00335             _buffer.append("/Helvetica findfont\n");
00336         }
00337 
00338         _buffer.append("" + size + " scalefont setfont\n");
00339         _currentFont = font;
00340     }
00341 
00342     public void setClip(Shape clip) {
00343     }
00344 
00345     public void setClip(int x, int y, int width, int height) {
00346     }
00347 
00352     public void setColor(Color c) {
00353         if (c == Color.black) {
00354             _buffer.append("0 setgray\n");
00355             _buffer.append("[] 0 setdash\n");
00356             _buffer.append("1 setlinewidth\n");
00357         } else if (c == Color.white) {
00358             _buffer.append("1 setgray\n");
00359             _buffer.append("[] 0 setdash\n");
00360             _buffer.append("1 setlinewidth\n");
00361         } else if (c == Color.lightGray) {
00362             _buffer.append("0.9 setgray\n");
00363             _buffer.append("[] 0 setdash\n");
00364             _buffer.append("0.5 setlinewidth\n");
00365         } else {
00366             if (_linepattern.containsKey(c)) {
00367                 _buffer.append((String) _linepattern.get(c) + " 0 setdash\n");
00368                 _buffer.append("1 setlinewidth\n");
00369             } else {
00370                 _buffer.append("0 setgray\n");
00371 
00372                 // construct a new line pattern.
00373                 if (_patternIndex >= _patterns.length) {
00374                     _patternIndex = 0;
00375                 }
00376 
00377                 _buffer.append(_patterns[_patternIndex] + " 0 setdash\n");
00378                 _buffer.append("1 setlinewidth\n");
00379                 _linepattern.put(c, _patterns[_patternIndex]);
00380                 _patternIndex++;
00381             }
00382         }
00383 
00384         _currentColor = c;
00385     }
00386 
00387     public void setPaintMode() {
00388     }
00389 
00390     public void setXORMode(Color c1) {
00391     }
00392 
00397     public void showpage() {
00398         _buffer.append("showpage\n");
00399 
00400         if (_out != null) {
00401             PrintWriter output = new PrintWriter(new BufferedOutputStream(_out));
00402 
00403             output.println(_buffer.toString());
00404             output.flush();
00405         } else {
00406             // Write to clipboard instead
00407             // NOTE: This doesn't work at least with jdk 1.3beta
00408             if (_clipboard == null) {
00409                 _clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
00410             }
00411 
00412             StringSelection sel = new StringSelection(_buffer.toString());
00413             _clipboard.setContents(sel, sel);
00414         }
00415     }
00416 
00417     public void translate(int x, int y) {
00418     }
00419 
00422     // Convert the screen coordinate system to that of postscript.
00423     private Point _convert(int x, int y) {
00424         return new Point(x + 50, (_height + 50) - y);
00425     }
00426 
00427     // Draw a closed polygon defined by arrays of x and y coordinates.
00428     // Return false if arguments are misformed.
00429     private boolean _polygon(int[] xPoints, int[] yPoints, int nPoints) {
00430         if ((nPoints < 3) || (xPoints.length < nPoints)
00431                 || (yPoints.length < nPoints)) {
00432             return false;
00433         }
00434 
00435         Point start = _convert(xPoints[0], yPoints[0]);
00436         _buffer.append("newpath " + start.x + " " + start.y + " moveto\n");
00437 
00438         for (int i = 1; i < nPoints; i++) {
00439             Point vertex = _convert(xPoints[i], yPoints[i]);
00440             _buffer.append("" + vertex.x + " " + vertex.y + " lineto\n");
00441         }
00442 
00443         return true;
00444     }
00445 
00446     // Issue a command to set the fill pattern.
00447     // Currently, this is a gray level that is a function of the color.
00448     private void _fillPattern() {
00449         // FIXME: We probably want a fill pattern rather than
00450         // just a gray scale.
00451         int red = _currentColor.getRed();
00452         int green = _currentColor.getGreen();
00453         int blue = _currentColor.getBlue();
00454 
00455         // Scaling constants so that fully saturated R, G, or B appear
00456         // different.
00457         double bluescale = 0.6; // darkest
00458         double redscale = 0.8;
00459         double greenscale = 1.0; // lightest
00460         double fullscale = Math.sqrt(255.0 * 255.0 * ((bluescale * bluescale)
00461                 + (redscale * redscale) + (greenscale * greenscale)));
00462         double graylevel = Math.sqrt(((red * red * redscale * redscale)
00463                 + (blue * blue * bluescale * bluescale) + (green * green
00464                 * greenscale * greenscale)))
00465                 / fullscale;
00466         _buffer.append("" + graylevel + " setgray\n");
00467 
00468         // NOTE -- for debugging, output color spec in comments
00469         _buffer.append("%---- rgb: " + red + " " + green + " " + blue + "\n");
00470     }
00471 
00474     private Color _currentColor = Color.black;
00475 
00476     private Font _currentFont;
00477 
00478     private int _width;
00479 
00480     private int _height;
00481 
00482     private Hashtable _linepattern = new Hashtable();
00483 
00484     private OutputStream _out;
00485 
00486     private StringBuffer _buffer = new StringBuffer();
00487 
00488     private Clipboard _clipboard;
00489 
00490     // Default line patterns.
00491     // FIXME: Need at least 11 of these.
00492     static private String[] _patterns = { "[]", "[1 1]", "[4 4]", "[4 4 1 4]",
00493             "[2 2]", "[4 2 1 2 1 2]", "[5 3 2 3]", "[3 3]", "[4 2 1 2 2 2]",
00494             "[1 2 5 2 1 2 1 2]", "[4 1 2 1]", };
00495 
00496     private int _patternIndex = 0;
00497 }