Back to index

wims  3.65+svn20090927
EPSGraphics.java
Go to the documentation of this file.
00001 package rene.zirkel.graphics;
00002 
00003 /* Graphics class supporting EPS export from plots.
00004 
00005 Copyright (c) 1998-2000 The Regents of the University of
00006 California.
00007 
00008 Modified, completed and extended by R. Grothmann
00009 
00010 */
00011 
00012 import java.awt.*;
00013 import java.awt.datatransfer.*;
00014 import java.io.*;
00015 import java.util.*;
00016 
00017 class EpsFontMetrics extends FontMetrics
00018 {      Font F;
00019 
00020        public EpsFontMetrics (Font f)
00021        {      super(f); // a dummy font.
00022               F=f;
00023        }
00024 
00025        public int stringWidth (String s)
00026        {      return s.length()*F.getSize()/2;
00027        }
00028        
00029        public int getHeight()
00030        {      return F.getSize(); 
00031        }
00032        
00033        public int getAscent()
00034        {      return F.getSize()*4/5; 
00035        }
00036        
00037 }
00038 
00039 class EpsPoint
00040 {      double x,y;
00041        public EpsPoint (double xx, double yy)
00042        {      x=xx; y=yy;
00043        }
00044 }
00045 
00046 public class EPSGraphics {
00047        
00049        //
00052        
00053        private Color _currentColor = Color.black; 
00054        private Font _currentFont; 
00055        private double _width, _height;
00056        int _orientation; 
00057        private Hashtable _linepattern = new Hashtable(); 
00058        private OutputStream _out; 
00059        private StringBuffer _buffer = new StringBuffer(); 
00060        private Clipboard _clipboard; 
00061        private double LineWidth=1;
00062        
00063        static private String[] _patterns = {
00064               "[]",
00065                      "[1 1]",
00066                      "[4 4]",
00067                      "[4 4 1 4]",
00068                      "[2 2]",
00069                      "[4 2 1 2 1 2]",
00070                      "[5 3 2 3]",
00071                      "[3 3]",
00072                      "[4 2 1 2 2 2]",
00073                      "[1 2 5 2 1 2 1 2]",
00074                      "[4 1 2 1]",
00075        }; 
00076 
00077        private int _patternIndex = 0; 
00078 
00079        public static final int PORTRAIT = 0; 
00080        public static final int LANDSCAPE = 1; 
00081 
00082        private FontMetrics FM;     
00083        
00084        public EPSGraphics (OutputStream out, double width, double height, 
00085               int orientation, boolean clip) {
00086               _width = width; 
00087               _height = height; 
00088               _orientation = orientation; 
00089               _out = out; 
00090               _buffer.append("%!PS-Adobe-3.0 EPSF-3.0\n"); 
00091               _buffer.append("%%Creator: QCircuitBuilder\n"); 
00092               _buffer.append("%%BoundingBox: 50 50 " + 
00093                      (int)(50+width) + " "+ (int)(50+height) +"\n"); 
00094               //_buffer.append("%%Orientation: " + (_orientation == PORTRAIT ? "Portrait" : "Landscape"));
00095               //_buffer.append("%%PageOrientation: " + (_orientation == PORTRAIT ? "Portrait" : "Landscape"));
00096               _buffer.append("%%Pages: 1\n"); 
00097               _buffer.append("%%Page: 1 1\n"); 
00098               _buffer.append("%%LanguageLevel: 2\n"); 
00099               if (clip) clipRect(0,0,width,height);
00100               _buffer.append("/Helvetica findfont 10 scalefont setfont\n");
00101        }      
00102        
00103        public void clearRect(int x, int y, int width, int height) 
00104        {
00105        }
00106        
00107        // Clip
00108        public void clipRect (double x, double y, double width, double height) {
00109               EpsPoint start = _convert(x, y); 
00110               //_fillPattern();
00111               _buffer.append("newpath " + round(start.x) + " " + round(start.y) + " moveto\n"); 
00112               _buffer.append("0 " + round(-height) + " rlineto\n"); 
00113               _buffer.append("" + round(width) + " 0 rlineto\n"); 
00114               _buffer.append("0 " + round(height) + " rlineto\n"); 
00115               _buffer.append("" + round(-width) + " 0 rlineto\n"); 
00116               _buffer.append("closepath clip\n"); 
00117        }
00118 
00119        private double round (double x)
00120        {      return Math.round(x*1000.0)/1000.0;
00121        }
00122        
00132        public void drawLine(double x1, double y1, double x2, double y2) 
00133        {      EpsPoint start = _convert(x1, y1); 
00134               EpsPoint end = _convert(x2, y2); 
00135               _buffer.append("newpath " + round(start.x) + " " + round(start.y) + " moveto\n"); 
00136               _buffer.append("" + round(end.x) + " " + round(end.y) + " lineto\n"); 
00137               _buffer.append("stroke\n"); 
00138        }
00139        
00153        public void drawPolygon(double xPoints[], double yPoints[], int
00154               nPoints) 
00155        {      if (!_polygon(xPoints, yPoints, nPoints)) {
00156                      return; 
00157               } else {
00158                      _buffer.append("closepath stroke\n"); 
00159               }
00160        }
00161        
00169        // FIXME: Currently, this ignores the fourth argument and
00170        // draws a circle with diameter given by the third argument.
00171        public void drawOval (double x, double y, double width, double height) 
00172        {
00173               double radius = width/2.0; 
00174               _buffer.append("newpath " + _convertX(x+radius) + " " + 
00175                      _convertY(y+radius) + " " + 
00176                      round(radius) + " 0 360 arc closepath stroke\n"); 
00177        }
00178        
00179        public void drawRect(double x, double y, double width, double height) {
00180               EpsPoint start = _convert(x, y); 
00181               _buffer.append("newpath " + round(start.x) + " " + round(start.y) + " moveto\n"); 
00182               _buffer.append("0 " + round(-height) + " rlineto\n"); 
00183               _buffer.append("" + round(width) + " 0 rlineto\n"); 
00184               _buffer.append("0 " + round(height) + " rlineto\n"); 
00185               _buffer.append("" + round(-width) + " 0 rlineto\n"); 
00186               _buffer.append("closepath stroke\n"); 
00187        }
00188        
00189        public void drawRoundRect(double x, double y, double width, double
00190               height,
00191               int arcWidth, int arcHeight) {
00192        }
00193        
00194        public void drawString(java.text.AttributedCharacterIterator
00195               iterator,
00196               int x, int y) {
00197        }
00198        
00199        public void drawString(String str, double x, double y) 
00200        {
00201               FontMetrics fm=getFontMetrics();
00202               EpsPoint start = _convert(x, y); 
00203               _buffer.append("" + start.x + " " + start.y + " moveto\n"); 
00204               _buffer.append("(" + str + ") show\n"); 
00205        }
00206        
00207        public void drawArc (double x, double y, double width, double height,
00208               double startAngle, double arcAngle) 
00209        {      double radius = width/2.0; 
00210               _buffer.append("newpath " +
00211                      _convertX(x+radius) + " " + 
00212                      _convertY(y+radius) + " " + 
00213                      round(radius) + " " + round(startAngle) + " " + " " +
00214                      round(startAngle+arcAngle) + " arc stroke\n"); 
00215        }
00216        
00217        public void fillArc (double x, double y, double width, double height,
00218               double startAngle, double arcAngle) 
00219        {      double radius = width/2.0;
00220               _buffer.append("newpath " + 
00221                      _convertX(x+radius) + " " + _convertY(y+radius) + " " +
00222                      " moveto " + 
00223                      _convertX(x+radius) + " " + _convertY(y+radius) + " " + 
00224                      radius + " " + round(startAngle) + " " +
00225                      round(startAngle+arcAngle) + 
00226                      " arc closepath fill\n"); 
00227        }
00228        
00229        public void fillChord (double x, double y, double width, double height,
00230               double startAngle, double arcAngle) 
00231        {      double radius = width/2.0;
00232               _buffer.append("newpath " + 
00233                      _convertX(x+radius) + " " + _convertY(y+radius) + " " + 
00234                      round(radius) + " " + round(startAngle) + " " +
00235                      round(startAngle+arcAngle) + 
00236                      " arc fill\n"); 
00237        }
00238        
00239        public void fillPolygon(double xPoints[], double yPoints[], int
00240               nPoints) 
00241        {      if (!_polygon(xPoints, yPoints, nPoints)) {
00242                      return; 
00243               } else {
00244                      _buffer.append("closepath fill\n"); 
00245               }
00246        }
00247        
00255        // FIXME: Currently, this ignores the fourth argument and draws a circle
00256        // with diameter given by the third argument.
00257        public void fillOval (double x, double y, double width, double height) 
00258        {
00259               double radius = width/2.0; 
00260               _buffer.append("newpath " + _convertX(x+radius) + " " + 
00261                      _convertY(y+radius) + " " + 
00262                      radius + " 0 360 arc closepath fill\n"); 
00263        }
00264        
00279        public void fillRect(double x, double y, double width, double height) {
00280               EpsPoint start = _convert(x, y); 
00281               //_fillPattern();
00282               _buffer.append("newpath " + start.x + " " + start.y + " moveto\n"); 
00283               _buffer.append("0 " + round(-height) + " rlineto\n"); 
00284               _buffer.append("" + round(width) + " 0 rlineto\n"); 
00285               _buffer.append("0 " + round(height) + " rlineto\n"); 
00286               _buffer.append("" + round(-width) + " 0 rlineto\n"); 
00287               _buffer.append("closepath gsave fill grestore\n"); 
00288               _buffer.append("0.5 setlinewidth 0 setgray [] 0 setdash stroke\n"); 
00289               // reset the gray scale to black
00290               _buffer.append(round(LineWidth)+" setlinewidth\n"); 
00291        }
00292        
00293        public void fillRoundRect(double x, double y, double width, double
00294               height,
00295               int arcWidth, int arcHeight) {
00296        }
00297        
00298        public Shape getClip() {
00299               return null; 
00300        }
00301        
00302        public Rectangle getClipBounds() {
00303               return null; 
00304        }
00305        
00306        public Color getColor() {
00307               return _currentColor; 
00308        }
00309        
00310        public Font getFont() {
00311               return _currentFont; 
00312        }
00313        
00314        public FontMetrics getFontMetrics (Font f)
00315        {      if (FM==null) FM=new EpsFontMetrics(new Font("dialog",Font.PLAIN,20)); 
00316               return FM; 
00317        }
00318        public FontMetrics getFontMetrics ()
00319        {      return getFontMetrics(_currentFont);
00320        }
00321        
00322        public void setFont (Font font) {
00323               int size = font.getSize(); 
00324               boolean bold = font.isBold(); 
00325               if (bold) {
00326                      _buffer.append("/Helvetica-Bold findfont\n"); 
00327               } else {
00328                      _buffer.append("/Helvetica findfont\n"); 
00329               }
00330               _buffer.append("" + size + " scalefont setfont\n"); 
00331               _currentFont = font;
00332               FM=new EpsFontMetrics(font); 
00333        }
00334        
00335        public void setClip(Shape clip) {
00336        }
00337        
00338        public void setClip(int x, int y, int width, int height) {
00339        }
00340        
00344        public void setColor(Color c) {
00345               _buffer.append(c.getRed()/255.0); 
00346               _buffer.append(" "); 
00347               _buffer.append(c.getGreen()/255.0); 
00348               
00349               _buffer.append(" "); 
00350               _buffer.append(c.getBlue()/255.0); 
00351               
00352               _buffer.append(" setrgbcolor\n"); 
00353               // _buffer.append("[] 0 setdash\n");
00354               // _buffer.append("1 setlinewidth\n");
00355               
00356               _currentColor = c; 
00357        }
00358 
00359        public void setLineWidth (double w)
00360        {      _buffer.append(round(w)+" setlinewidth\n");
00361               LineWidth=w;
00362        }
00363        
00364        public void setDash (double a, double b)
00365        {      _buffer.append("["+round(a)+" "+round(b)+" ] 0 setdash\n");
00366        }
00367        
00368        public void clearDash ()
00369        {      _buffer.append("[ ] 0 setdash\n");
00370        }
00371        
00372        public void setPaintMode() {
00373        }
00374        
00375        public void setXORMode(Color c1) {
00376        }
00377        
00382        public void showpage (String name) {
00383               try {
00384                      //_buffer.append("showpage\n"); 
00385                      _buffer.append("%%EOF"); 
00386                      
00387                      PrintWriter output = new PrintWriter(
00388                             new java.io.FileWriter(name)); 
00389                      
00390                      output.println(_buffer.toString()); 
00391                      output.flush(); 
00392                      
00393               }
00394               catch(Exception e) { e.printStackTrace(); }
00395        }
00396        
00401        public void close ()
00402               throws IOException 
00403        {
00404                      _buffer.append("showpage\n"); 
00405                      _buffer.append("%%EOF"); 
00406        
00407                      PrintWriter output=new PrintWriter(_out);
00408                      
00409                      output.println(_buffer.toString()); 
00410                      output.flush(); 
00411                      
00412        }
00413        
00415        //
00418        
00419        // Convert the screen coordinate system to that of postscript.
00420        private EpsPoint _convert (double x, double y) {
00421               return new EpsPoint(round(x+50),round(_height+50 - y)); 
00422        }
00423        
00424        private double _convertX (double x) 
00425        {      return round(x+50);
00426        }
00427        private double _convertY (double y) 
00428        {      return round(_height+50-y);
00429        }
00430 
00431        // Draw a closed polygon defined by arrays of x and y coordinates.
00432        // Return false if arguments are misformed.
00433        private boolean _polygon(double xPoints[], double yPoints[], int
00434               nPoints) {
00435               if (nPoints < 3 || xPoints.length < nPoints
00436                      || yPoints.length < nPoints) return false; 
00437               EpsPoint start = _convert(xPoints[0], yPoints[0]); 
00438               _buffer.append("newpath " + round(start.x) + " " + round(start.y) + " moveto\n"); 
00439               for (int i = 1; i < nPoints; i++) {
00440                      EpsPoint vertex = _convert(xPoints[i], yPoints[i]); 
00441                      _buffer.append("" + round(vertex.x) + " " + round(vertex.y) + " lineto\n"); 
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               // Scaling constants so that fully saturated R, G, or B appear
00455               // different.
00456               double bluescale = 0.6; // darkest
00457               double redscale = 0.8; 
00458               double greenscale = 1.0; // lightest
00459               double fullscale =
00460                      Math.sqrt(255.0*255.0*(bluescale*bluescale
00461                      + redscale*redscale + greenscale*greenscale)); 
00462               double graylevel =
00463                      Math.sqrt((double)(red*red*redscale*redscale
00464                      + blue*blue*bluescale*bluescale
00465                      + green*green*greenscale*greenscale))/fullscale; 
00466               _buffer.append("" + graylevel + " setgray\n"); 
00467               // NOTE -- for debugging, output color spec in comments
00468               _buffer.append("rgb: " + red + " " +
00469                      green + " " + blue +"\n"); 
00470        }
00471 
00472 }