2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package org.jibble.epsgraphics;
23 import jalview.util.MessageManager;
25 import java.awt.AlphaComposite;
26 import java.awt.BasicStroke;
27 import java.awt.Color;
28 import java.awt.Composite;
30 import java.awt.FontMetrics;
31 import java.awt.Graphics;
32 import java.awt.GraphicsConfiguration;
33 import java.awt.GraphicsDevice;
34 import java.awt.GraphicsEnvironment;
35 import java.awt.Image;
36 import java.awt.Paint;
37 import java.awt.Polygon;
38 import java.awt.Rectangle;
39 import java.awt.RenderingHints;
40 import java.awt.Shape;
41 import java.awt.Stroke;
42 import java.awt.font.FontRenderContext;
43 import java.awt.font.GlyphVector;
44 import java.awt.font.TextAttribute;
45 import java.awt.font.TextLayout;
46 import java.awt.geom.AffineTransform;
47 import java.awt.geom.Arc2D;
48 import java.awt.geom.Area;
49 import java.awt.geom.Ellipse2D;
50 import java.awt.geom.GeneralPath;
51 import java.awt.geom.Line2D;
52 import java.awt.geom.PathIterator;
53 import java.awt.geom.Point2D;
54 import java.awt.geom.Rectangle2D;
55 import java.awt.geom.RoundRectangle2D;
56 import java.awt.image.BufferedImage;
57 import java.awt.image.BufferedImageOp;
58 import java.awt.image.ColorModel;
59 import java.awt.image.ImageObserver;
60 import java.awt.image.PixelGrabber;
61 import java.awt.image.RenderedImage;
62 import java.awt.image.WritableRaster;
63 import java.awt.image.renderable.RenderableImage;
65 import java.io.FileOutputStream;
66 import java.io.IOException;
67 import java.io.OutputStream;
68 import java.io.StringWriter;
69 import java.text.AttributedCharacterIterator;
70 import java.text.AttributedString;
71 import java.text.CharacterIterator;
72 import java.util.Hashtable;
76 * EpsGraphics2D is suitable for creating high quality EPS graphics for use in
77 * documents and papers, and can be used just like a standard Graphics2D object.
79 * Many Java programs use Graphics2D to draw stuff on the screen, and while it
80 * is easy to save the output as a png or jpeg file, it is a little harder to
81 * export it as an EPS for including in a document or paper.
83 * This class makes the whole process extremely easy, because you can use it as
84 * if it's a Graphics2D object. The only difference is that all of the
85 * implemented methods create EPS output, which means the diagrams you draw can
86 * be resized without leading to any of the jagged edges you may see when
87 * resizing pixel-based images, such as jpeg and png files.
93 * Graphics2D g = new EpsGraphics2D();
94 * g.setColor(Color.black);
96 * // Line thickness 2.
97 * g.setStroke(new BasicStroke(2.0f));
100 * g.drawLine(10, 10, 50, 10);
102 * // Fill a rectangle in blue
103 * g.setColor(Color.blue);
104 * g.fillRect(10, 0, 20, 20);
106 * // Get the EPS output.
107 * String output = g.toString();
111 * You do not need to worry about the size of the canvas when drawing on a
112 * EpsGraphics2D object. The bounding box of the EPS document will automatically
113 * resize to accomodate new items that you draw.
115 * Not all methods are implemented yet. Those that are not are clearly labelled.
117 * Copyright Paul Mutton, <a
118 * href="http://www.jibble.org/">http://www.jibble.org/</a>
121 public class EpsGraphics2D extends java.awt.Graphics2D
124 public static final String VERSION = "0.8.8";
127 * Constructs a new EPS document that is initially empty and can be drawn on
128 * like a Graphics2D object. The EPS document is stored in memory.
130 public EpsGraphics2D()
136 * Constructs a new EPS document that is initially empty and can be drawn on
137 * like a Graphics2D object. The EPS document is stored in memory.
139 public EpsGraphics2D(String title)
141 _document = new EpsDocument(title);
142 _backgroundColor = Color.white;
144 _transform = new AffineTransform();
145 _clipTransform = new AffineTransform();
146 _accurateTextMode = true;
147 setColor(Color.black);
148 setPaint(Color.black);
149 setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
150 setFont(Font.decode(null));
151 setStroke(new BasicStroke());
155 * Constructs a new EPS document that is initially empty and can be drawn on
156 * like a Graphics2D object. The EPS document is written to the file as it
157 * goes, which reduces memory usage. The bounding box of the document is fixed
158 * and specified at construction time by minX,minY,maxX,maxY. The file is
159 * flushed and closed when the close() method is called.
161 public EpsGraphics2D(String title, File file, int minX, int minY,
162 int maxX, int maxY) throws IOException
164 this(title, new FileOutputStream(file), minX, minY, maxX, maxY);
168 * Constructs a new EPS document that is initially empty and can be drawn on
169 * like a Graphics2D object. The EPS document is written to the output stream
170 * as it goes, which reduces memory usage. The bounding box of the document is
171 * fixed and specified at construction time by minX,minY,maxX,maxY. The output
172 * stream is flushed and closed when the close() method is called.
174 public EpsGraphics2D(String title, OutputStream outputStream, int minX,
175 int minY, int maxX, int maxY) throws IOException
178 _document = new EpsDocument(title, outputStream, minX, minY, maxX, maxY);
182 * Constructs a new EpsGraphics2D instance that is a copy of the supplied
183 * argument and points at the same EpsDocument.
185 protected EpsGraphics2D(EpsGraphics2D g)
187 _document = g._document;
188 _backgroundColor = g._backgroundColor;
190 _clipTransform = (AffineTransform) g._clipTransform.clone();
191 _transform = (AffineTransform) g._transform.clone();
194 _composite = g._composite;
197 _accurateTextMode = g._accurateTextMode;
201 * This method is called to indicate that a particular method is not supported
202 * yet. The stack trace is printed to the standard output.
204 private void methodNotSupported()
206 EpsException e = new EpsException(MessageManager.formatMessage(
207 "exception.eps_method_not_supported", new String[] { VERSION }));
208 e.printStackTrace(System.err);
211 // ///////////// Specialist methods ///////////////////////
214 * Sets whether to use accurate text mode when rendering text in EPS. This is
215 * enabled (true) by default. When accurate text mode is used, all text will
216 * be rendered in EPS to appear exactly the same as it would do when drawn
217 * with a Graphics2D context. With accurate text mode enabled, it is not
218 * necessary for the EPS viewer to have the required font installed.
220 * Turning off accurate text mode will require the EPS viewer to have the
221 * necessary fonts installed. If you are using a lot of text, you will find
222 * that this significantly reduces the file size of your EPS documents.
223 * AffineTransforms can only affect the starting point of text using this
224 * simpler text mode - all text will be horizontal.
226 public void setAccurateTextMode(boolean b)
228 _accurateTextMode = b;
232 * Returns whether accurate text mode is being used.
234 public boolean getAccurateTextMode()
236 return _accurateTextMode;
240 * Flushes the buffered contents of this EPS document to the underlying
241 * OutputStream it is being written to.
243 public void flush() throws IOException
249 * Closes the EPS file being output to the underlying OutputStream. The
250 * OutputStream is automatically flushed before being closed. If you forget to
251 * do this, the file may be incomplete.
253 public void close() throws IOException
260 * Appends a line to the EpsDocument.
262 private void append(String line)
264 _document.append(this, line);
268 * Returns the point after it has been transformed by the transformation.
270 private Point2D transform(float x, float y)
272 Point2D result = new Point2D.Float(x, y);
273 result = _transform.transform(result, result);
274 result.setLocation(result.getX(), -result.getY());
279 * Appends the commands required to draw a shape on the EPS document.
281 private void draw(Shape s, String action)
287 // Rectangle2D userBounds = s.getBounds2D();
288 if (!_transform.isIdentity())
290 s = _transform.createTransformedShape(s);
293 // Update the bounds.
294 if (!action.equals("clip"))
296 Rectangle2D shapeBounds = s.getBounds2D();
297 Rectangle2D visibleBounds = shapeBounds;
300 Rectangle2D clipBounds = _clip.getBounds2D();
301 visibleBounds = shapeBounds.createIntersection(clipBounds);
303 float lineRadius = _stroke.getLineWidth() / 2;
304 float minX = (float) visibleBounds.getMinX() - lineRadius;
305 float minY = (float) visibleBounds.getMinY() - lineRadius;
306 float maxX = (float) visibleBounds.getMaxX() + lineRadius;
307 float maxY = (float) visibleBounds.getMaxY() + lineRadius;
308 _document.updateBounds(minX, -minY);
309 _document.updateBounds(maxX, -maxY);
314 float[] coords = new float[6];
315 PathIterator it = s.getPathIterator(null);
321 type = it.currentSegment(coords);
322 float x1 = coords[0];
323 float y1 = -coords[1];
324 float x2 = coords[2];
325 float y2 = -coords[3];
326 float x3 = coords[4];
327 float y3 = -coords[5];
329 if (type == PathIterator.SEG_CLOSE)
334 else if (type == PathIterator.SEG_CUBICTO)
336 append(x1 + " " + y1 + " " + x2 + " " + y2 + " " + x3 + " " + y3
342 else if (type == PathIterator.SEG_LINETO)
344 append(x1 + " " + y1 + " lineto");
349 else if (type == PathIterator.SEG_MOVETO)
351 append(x1 + " " + y1 + " moveto");
356 else if (type == PathIterator.SEG_QUADTO)
358 // Convert the quad curve into a cubic.
359 float _x1 = x0 + 2 / 3f * (x1 - x0);
360 float _y1 = y0 + 2 / 3f * (y1 - y0);
361 float _x2 = x1 + 1 / 3f * (x2 - x1);
362 float _y2 = y1 + 1 / 3f * (y2 - y1);
365 append(_x1 + " " + _y1 + " " + _x2 + " " + _y2 + " " + _x3 + " "
371 else if (type == PathIterator.WIND_EVEN_ODD)
375 else if (type == PathIterator.WIND_NON_ZERO)
387 * Returns a hex string that always contains two characters.
389 private String toHexString(int n)
391 String result = Integer.toString(n, 16);
392 while (result.length() < 2)
394 result = "0" + result;
399 // ///////////// Graphics2D methods ///////////////////////
402 * Draws a 3D rectangle outline. If it is raised, light appears to come from
405 public void draw3DRect(int x, int y, int width, int height, boolean raised)
407 Color originalColor = getColor();
408 Stroke originalStroke = getStroke();
410 setStroke(new BasicStroke(1.0f));
414 setColor(originalColor.brighter());
418 setColor(originalColor.darker());
421 drawLine(x, y, x + width, y);
422 drawLine(x, y, x, y + height);
426 setColor(originalColor.darker());
430 setColor(originalColor.brighter());
433 drawLine(x + width, y + height, x, y + height);
434 drawLine(x + width, y + height, x + width, y);
436 setColor(originalColor);
437 setStroke(originalStroke);
441 * Fills a 3D rectangle. If raised, it has bright fill and light appears to
442 * come from the top left.
444 public void fill3DRect(int x, int y, int width, int height, boolean raised)
446 Color originalColor = getColor();
450 setColor(originalColor.brighter());
454 setColor(originalColor.darker());
456 draw(new Rectangle(x, y, width, height), "fill");
457 setColor(originalColor);
458 draw3DRect(x, y, width, height, raised);
462 * Draws a Shape on the EPS document.
464 public void draw(Shape s)
470 * Draws an Image on the EPS document.
472 public boolean drawImage(Image img, AffineTransform xform,
475 AffineTransform at = getTransform();
477 boolean st = drawImage(img, 0, 0, obs);
483 * Draws a BufferedImage on the EPS document.
485 public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y)
487 BufferedImage img1 = op.filter(img, null);
488 drawImage(img1, new AffineTransform(1f, 0f, 0f, 1f, x, y), null);
492 * Draws a RenderedImage on the EPS document.
494 public void drawRenderedImage(RenderedImage img, AffineTransform xform)
496 Hashtable properties = new Hashtable();
497 String[] names = img.getPropertyNames();
498 for (int i = 0; i < names.length; i++)
500 properties.put(names[i], img.getProperty(names[i]));
503 ColorModel cm = img.getColorModel();
504 WritableRaster wr = img.copyData(null);
505 BufferedImage img1 = new BufferedImage(cm, wr,
506 cm.isAlphaPremultiplied(), properties);
507 AffineTransform at = AffineTransform.getTranslateInstance(
508 img.getMinX(), img.getMinY());
509 at.preConcatenate(xform);
510 drawImage(img1, at, null);
514 * Draws a RenderableImage by invoking its createDefaultRendering method.
516 public void drawRenderableImage(RenderableImage img, AffineTransform xform)
518 drawRenderedImage(img.createDefaultRendering(), xform);
522 * Draws a string at (x,y)
524 public void drawString(String str, int x, int y)
526 drawString(str, (float) x, (float) y);
530 * Draws a string at (x,y)
532 public void drawString(String s, float x, float y)
534 if (s != null && s.length() > 0)
536 AttributedString as = new AttributedString(s);
537 as.addAttribute(TextAttribute.FONT, getFont());
538 drawString(as.getIterator(), x, y);
543 * Draws the characters of an AttributedCharacterIterator, starting from
546 public void drawString(AttributedCharacterIterator iterator, int x, int y)
548 drawString(iterator, (float) x, (float) y);
552 * Draws the characters of an AttributedCharacterIterator, starting from
555 public void drawString(AttributedCharacterIterator iterator, float x,
558 if (getAccurateTextMode())
560 TextLayout layout = new TextLayout(iterator, getFontRenderContext());
561 Shape shape = layout.getOutline(AffineTransform.getTranslateInstance(
568 Point2D location = transform(x, y);
569 append(location.getX() + " " + location.getY() + " moveto");
570 StringBuffer buffer = new StringBuffer();
571 for (char ch = iterator.first(); ch != CharacterIterator.DONE; ch = iterator
574 if (ch == '(' || ch == ')')
580 append("(" + buffer.toString() + ") show");
585 * Draws a GlyphVector at (x,y)
587 public void drawGlyphVector(GlyphVector g, float x, float y)
589 Shape shape = g.getOutline(x, y);
594 * Fills a Shape on the EPS document.
596 public void fill(Shape s)
602 * Checks whether or not the specified Shape intersects the specified
603 * Rectangle, which is in device space.
605 public boolean hit(Rectangle rect, Shape s, boolean onStroke)
607 return s.intersects(rect);
611 * Returns the device configuration associated with this EpsGraphics2D object.
613 public GraphicsConfiguration getDeviceConfiguration()
615 GraphicsConfiguration gc = null;
616 GraphicsEnvironment ge = GraphicsEnvironment
617 .getLocalGraphicsEnvironment();
618 GraphicsDevice[] gds = ge.getScreenDevices();
619 for (int i = 0; i < gds.length; i++)
621 GraphicsDevice gd = gds[i];
622 GraphicsConfiguration[] gcs = gd.getConfigurations();
632 * Sets the Composite to be used by this EpsGraphics2D. EpsGraphics2D does not
635 public void setComposite(Composite comp)
641 * Sets the Paint attribute for the EpsGraphics2D object. Only Paint objects
642 * of type Color are respected by EpsGraphics2D.
644 public void setPaint(Paint paint)
647 if (paint instanceof Color)
649 setColor((Color) paint);
654 * Sets the stroke. Only accepts BasicStroke objects (or subclasses of
657 public void setStroke(Stroke s)
659 if (s instanceof BasicStroke)
661 _stroke = (BasicStroke) s;
663 append(_stroke.getLineWidth() + " setlinewidth");
664 float miterLimit = _stroke.getMiterLimit();
665 if (miterLimit < 1.0f)
669 append(miterLimit + " setmiterlimit");
670 append(_stroke.getLineJoin() + " setlinejoin");
671 append(_stroke.getEndCap() + " setlinecap");
673 StringBuffer dashes = new StringBuffer();
675 float[] dashArray = _stroke.getDashArray();
676 if (dashArray != null)
678 for (int i = 0; i < dashArray.length; i++)
680 dashes.append((dashArray[i]) + " ");
684 append(dashes.toString() + " 0 setdash");
689 * Sets a rendering hint. These are not used by EpsGraphics2D.
691 public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue)
697 * Returns the value of a single preference for the rendering algorithms.
698 * Rendering hints are not used by EpsGraphics2D.
700 public Object getRenderingHint(RenderingHints.Key hintKey)
706 * Sets the rendering hints. These are ignored by EpsGraphics2D.
708 public void setRenderingHints(Map hints)
714 * Adds rendering hints. These are ignored by EpsGraphics2D.
716 public void addRenderingHints(Map hints)
722 * Returns the preferences for the rendering algorithms.
724 public RenderingHints getRenderingHints()
726 return new RenderingHints(null);
730 * Translates the origin of the EpsGraphics2D context to the point (x,y) in
731 * the current coordinate system.
733 public void translate(int x, int y)
735 translate((double) x, (double) y);
739 * Concatenates the current EpsGraphics2D Transformation with a translation
742 public void translate(double tx, double ty)
744 transform(AffineTransform.getTranslateInstance(tx, ty));
748 * Concatenates the current EpsGraphics2D Transform with a rotation transform.
750 public void rotate(double theta)
756 * Concatenates the current EpsGraphics2D Transform with a translated rotation
759 public void rotate(double theta, double x, double y)
761 transform(AffineTransform.getRotateInstance(theta, x, y));
765 * Concatenates the current EpsGraphics2D Transform with a scaling
768 public void scale(double sx, double sy)
770 transform(AffineTransform.getScaleInstance(sx, sy));
774 * Concatenates the current EpsGraphics2D Transform with a shearing transform.
776 public void shear(double shx, double shy)
778 transform(AffineTransform.getShearInstance(shx, shy));
782 * Composes an AffineTransform object with the Transform in this EpsGraphics2D
783 * according to the rule last-specified-first-applied.
785 public void transform(AffineTransform Tx)
787 _transform.concatenate(Tx);
788 setTransform(getTransform());
792 * Sets the AffineTransform to be used by this EpsGraphics2D.
794 public void setTransform(AffineTransform Tx)
798 _transform = new AffineTransform();
802 _transform = new AffineTransform(Tx);
804 // Need to update the stroke and font so they know the scale changed
805 setStroke(getStroke());
810 * Gets the AffineTransform used by this EpsGraphics2D.
812 public AffineTransform getTransform()
814 return new AffineTransform(_transform);
818 * Returns the current Paint of the EpsGraphics2D object.
820 public Paint getPaint()
826 * returns the current Composite of the EpsGraphics2D object.
828 public Composite getComposite()
834 * Sets the background color to be used by the clearRect method.
836 public void setBackground(Color color)
842 _backgroundColor = color;
846 * Gets the background color that is used by the clearRect method.
848 public Color getBackground()
850 return _backgroundColor;
854 * Returns the Stroke currently used. Guaranteed to be an instance of
857 public Stroke getStroke()
863 * Intersects the current clip with the interior of the specified Shape and
864 * sets the clip to the resulting intersection.
866 public void clip(Shape s)
874 Area area = new Area(_clip);
875 area.intersect(new Area(s));
881 * Returns the FontRenderContext.
883 public FontRenderContext getFontRenderContext()
885 return _fontRenderContext;
888 // ///////////// Graphics methods ///////////////////////
891 * Returns a new Graphics object that is identical to this EpsGraphics2D.
893 public Graphics create()
895 return new EpsGraphics2D(this);
899 * Returns an EpsGraphics2D object based on this Graphics object, but with a
900 * new translation and clip area.
902 public Graphics create(int x, int y, int width, int height)
904 Graphics g = create();
906 g.clipRect(0, 0, width, height);
911 * Returns the current Color. This will be a default value (black) until it is
912 * changed using the setColor method.
914 public Color getColor()
920 * Sets the Color to be used when drawing all future shapes, text, etc.
922 public void setColor(Color c)
929 append((c.getRed() / 255f) + " " + (c.getGreen() / 255f) + " "
930 + (c.getBlue() / 255f) + " setrgbcolor");
934 * Sets the paint mode of this EpsGraphics2D object to overwrite the
935 * destination EpsDocument with the current color.
937 public void setPaintMode()
939 // Do nothing - paint mode is the only method supported anyway.
943 * <b><i><font color="red">Not implemented</font></i></b> - performs no
946 public void setXORMode(Color c1)
948 methodNotSupported();
952 * Returns the Font currently being used.
954 public Font getFont()
960 * Sets the Font to be used in future text.
962 public void setFont(Font font)
966 font = Font.decode(null);
969 append("/" + _font.getPSName() + " findfont " + ((int) _font.getSize())
970 + " scalefont setfont");
974 * Gets the font metrics of the current font.
976 public FontMetrics getFontMetrics()
978 return getFontMetrics(getFont());
982 * Gets the font metrics for the specified font.
984 public FontMetrics getFontMetrics(Font f)
986 BufferedImage image = new BufferedImage(1, 1,
987 BufferedImage.TYPE_INT_RGB);
988 Graphics g = image.getGraphics();
989 return g.getFontMetrics(f);
993 * Returns the bounding rectangle of the current clipping area.
995 public Rectangle getClipBounds()
1001 Rectangle rect = getClip().getBounds();
1006 * Intersects the current clip with the specified rectangle.
1008 public void clipRect(int x, int y, int width, int height)
1010 clip(new Rectangle(x, y, width, height));
1014 * Sets the current clip to the rectangle specified by the given coordinates.
1016 public void setClip(int x, int y, int width, int height)
1018 setClip(new Rectangle(x, y, width, height));
1022 * Gets the current clipping area.
1024 public Shape getClip()
1034 AffineTransform t = _transform.createInverse();
1035 t.concatenate(_clipTransform);
1036 return t.createTransformedShape(_clip);
1037 } catch (Exception e)
1039 throw new EpsException(MessageManager.formatMessage(
1040 "exception.eps_unable_to_get_inverse_matrix",
1041 new String[] { _transform.toString() }));
1047 * Sets the current clipping area to an arbitrary clip shape.
1049 public void setClip(Shape clip)
1053 if (_document.isClipSet())
1060 _document.setClipSet(true);
1065 _clipTransform = (AffineTransform) _transform.clone();
1069 if (_document.isClipSet())
1072 _document.setClipSet(false);
1079 * <b><i><font color="red">Not implemented</font></i></b> - performs no
1082 public void copyArea(int x, int y, int width, int height, int dx, int dy)
1084 methodNotSupported();
1088 * Draws a straight line from (x1,y1) to (x2,y2).
1090 public void drawLine(int x1, int y1, int x2, int y2)
1092 Shape shape = new Line2D.Float(x1, y1, x2, y2);
1097 * Fills a rectangle with top-left corner placed at (x,y).
1099 public void fillRect(int x, int y, int width, int height)
1101 Shape shape = new Rectangle(x, y, width, height);
1102 draw(shape, "fill");
1106 * Draws a rectangle with top-left corner placed at (x,y).
1108 public void drawRect(int x, int y, int width, int height)
1110 Shape shape = new Rectangle(x, y, width, height);
1115 * Clears a rectangle with top-left corner placed at (x,y) using the current
1118 public void clearRect(int x, int y, int width, int height)
1120 Color originalColor = getColor();
1122 setColor(getBackground());
1123 Shape shape = new Rectangle(x, y, width, height);
1124 draw(shape, "fill");
1126 setColor(originalColor);
1130 * Draws a rounded rectangle.
1132 public void drawRoundRect(int x, int y, int width, int height,
1133 int arcWidth, int arcHeight)
1135 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
1141 * Fills a rounded rectangle.
1143 public void fillRoundRect(int x, int y, int width, int height,
1144 int arcWidth, int arcHeight)
1146 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
1148 draw(shape, "fill");
1154 public void drawOval(int x, int y, int width, int height)
1156 Shape shape = new Ellipse2D.Float(x, y, width, height);
1163 public void fillOval(int x, int y, int width, int height)
1165 Shape shape = new Ellipse2D.Float(x, y, width, height);
1166 draw(shape, "fill");
1172 public void drawArc(int x, int y, int width, int height, int startAngle,
1175 Shape shape = new Arc2D.Float(x, y, width, height, startAngle,
1176 arcAngle, Arc2D.OPEN);
1183 public void fillArc(int x, int y, int width, int height, int startAngle,
1186 Shape shape = new Arc2D.Float(x, y, width, height, startAngle,
1187 arcAngle, Arc2D.PIE);
1188 draw(shape, "fill");
1194 public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
1198 GeneralPath path = new GeneralPath();
1199 path.moveTo(xPoints[0], yPoints[0]);
1200 for (int i = 1; i < nPoints; i++)
1202 path.lineTo(xPoints[i], yPoints[i]);
1209 * Draws a polygon made with the specified points.
1211 public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
1213 Shape shape = new Polygon(xPoints, yPoints, nPoints);
1220 public void drawPolygon(Polygon p)
1226 * Fills a polygon made with the specified points.
1228 public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
1230 Shape shape = new Polygon(xPoints, yPoints, nPoints);
1231 draw(shape, "fill");
1237 public void fillPolygon(Polygon p)
1243 * Draws the specified characters, starting from (x,y)
1245 public void drawChars(char[] data, int offset, int length, int x, int y)
1247 String string = new String(data, offset, length);
1248 drawString(string, x, y);
1252 * Draws the specified bytes, starting from (x,y)
1254 public void drawBytes(byte[] data, int offset, int length, int x, int y)
1256 String string = new String(data, offset, length);
1257 drawString(string, x, y);
1263 public boolean drawImage(Image img, int x, int y, ImageObserver observer)
1265 return drawImage(img, x, y, Color.white, observer);
1271 public boolean drawImage(Image img, int x, int y, int width, int height,
1272 ImageObserver observer)
1274 return drawImage(img, x, y, width, height, Color.white, observer);
1280 public boolean drawImage(Image img, int x, int y, Color bgcolor,
1281 ImageObserver observer)
1283 int width = img.getWidth(null);
1284 int height = img.getHeight(null);
1285 return drawImage(img, x, y, width, height, bgcolor, observer);
1291 public boolean drawImage(Image img, int x, int y, int width, int height,
1292 Color bgcolor, ImageObserver observer)
1294 return drawImage(img, x, y, x + width, y + height, 0, 0, width, height,
1301 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
1302 int sx1, int sy1, int sx2, int sy2, ImageObserver observer)
1304 return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1305 Color.white, observer);
1311 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
1312 int sx1, int sy1, int sx2, int sy2, Color bgcolor,
1313 ImageObserver observer)
1317 throw new IllegalArgumentException("dx1 >= dx2");
1321 throw new IllegalArgumentException("sx1 >= sx2");
1325 throw new IllegalArgumentException("dy1 >= dy2");
1329 throw new IllegalArgumentException("sy1 >= sy2");
1334 int width = sx2 - sx1;
1335 int height = sy2 - sy1;
1336 int destWidth = dx2 - dx1;
1337 int destHeight = dy2 - dy1;
1339 int[] pixels = new int[width * height];
1340 PixelGrabber pg = new PixelGrabber(img, sx1, sy1, sx2 - sx1, sy2 - sy1,
1345 } catch (InterruptedException e)
1350 AffineTransform matrix = new AffineTransform(_transform);
1351 matrix.translate(dx1, dy1);
1352 matrix.scale(destWidth / (double) width, destHeight / (double) height);
1353 double[] m = new double[6];
1356 matrix = matrix.createInverse();
1357 } catch (Exception e)
1359 throw new EpsException(MessageManager.formatMessage(
1360 "exception.eps_unable_to_get_inverse_matrix",
1361 new String[] { matrix.toString() }));
1363 matrix.scale(1, -1);
1364 matrix.getMatrix(m);
1365 append(width + " " + height + " 8 [" + m[0] + " " + m[1] + " " + m[2]
1366 + " " + m[3] + " " + m[4] + " " + m[5] + "]");
1367 // Fill the background to update the bounding box.
1368 Color oldColor = getColor();
1369 setColor(getBackground());
1370 fillRect(dx1, dy1, destWidth, destHeight);
1372 append("{currentfile 3 " + width
1373 + " mul string readhexstring pop} bind");
1374 append("false 3 colorimage");
1375 StringBuffer line = new StringBuffer();
1376 for (int y = 0; y < height; y++)
1378 for (int x = 0; x < width; x++)
1380 Color color = new Color(pixels[x + width * y]);
1381 line.append(toHexString(color.getRed())
1382 + toHexString(color.getGreen())
1383 + toHexString(color.getBlue()));
1384 if (line.length() > 64)
1386 append(line.toString());
1387 line = new StringBuffer();
1391 if (line.length() > 0)
1393 append(line.toString());
1402 * Disposes of all resources used by this EpsGraphics2D object. If this is the
1403 * only remaining EpsGraphics2D instance pointing at a EpsDocument object,
1404 * then the EpsDocument object shall become eligible for garbage collection.
1406 public void dispose()
1412 * Finalizes the object.
1414 public void finalize()
1420 * Returns the entire contents of the EPS document, complete with headers and
1421 * bounding box. The returned String is suitable for being written directly to
1422 * disk as an EPS file.
1424 public String toString()
1426 StringWriter writer = new StringWriter();
1429 _document.write(writer);
1432 } catch (IOException e)
1434 throw new EpsException(e.toString());
1436 return writer.toString();
1440 * Returns true if the specified rectangular area might intersect the current
1443 public boolean hitClip(int x, int y, int width, int height)
1449 Rectangle rect = new Rectangle(x, y, width, height);
1450 return hit(rect, _clip, true);
1454 * Returns the bounding rectangle of the current clipping area.
1456 public Rectangle getClipBounds(Rectangle r)
1462 Rectangle rect = getClipBounds();
1463 r.setLocation((int) rect.getX(), (int) rect.getY());
1464 r.setSize((int) rect.getWidth(), (int) rect.getHeight());
1468 private Color _color;
1470 private Color _backgroundColor;
1472 private Paint _paint;
1474 private Composite _composite;
1476 private BasicStroke _stroke;
1480 private Shape _clip;
1482 private AffineTransform _clipTransform;
1484 private AffineTransform _transform;
1486 private boolean _accurateTextMode;
1488 private EpsDocument _document;
1490 private static FontRenderContext _fontRenderContext = new FontRenderContext(