2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 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;
28 import java.awt.font.*;
29 import java.awt.geom.*;
30 import java.awt.image.*;
31 import java.awt.image.renderable.*;
34 * EpsGraphics2D is suitable for creating high quality EPS graphics for use in
35 * documents and papers, and can be used just like a standard Graphics2D object.
37 * Many Java programs use Graphics2D to draw stuff on the screen, and while it
38 * is easy to save the output as a png or jpeg file, it is a little harder to
39 * export it as an EPS for including in a document or paper.
41 * This class makes the whole process extremely easy, because you can use it as
42 * if it's a Graphics2D object. The only difference is that all of the
43 * implemented methods create EPS output, which means the diagrams you draw can
44 * be resized without leading to any of the jagged edges you may see when
45 * resizing pixel-based images, such as jpeg and png files.
51 * Graphics2D g = new EpsGraphics2D();
52 * g.setColor(Color.black);
54 * // Line thickness 2.
55 * g.setStroke(new BasicStroke(2.0f));
58 * g.drawLine(10, 10, 50, 10);
60 * // Fill a rectangle in blue
61 * g.setColor(Color.blue);
62 * g.fillRect(10, 0, 20, 20);
64 * // Get the EPS output.
65 * String output = g.toString();
69 * You do not need to worry about the size of the canvas when drawing on a
70 * EpsGraphics2D object. The bounding box of the EPS document will automatically
71 * resize to accomodate new items that you draw.
73 * Not all methods are implemented yet. Those that are not are clearly labelled.
75 * Copyright Paul Mutton, <a
76 * href="http://www.jibble.org/">http://www.jibble.org/</a>
79 public class EpsGraphics2D extends java.awt.Graphics2D
82 public static final String VERSION = "0.8.8";
85 * Constructs a new EPS document that is initially empty and can be drawn on
86 * like a Graphics2D object. The EPS document is stored in memory.
88 public EpsGraphics2D()
94 * Constructs a new EPS document that is initially empty and can be drawn on
95 * like a Graphics2D object. The EPS document is stored in memory.
97 public EpsGraphics2D(String title)
99 _document = new EpsDocument(title);
100 _backgroundColor = Color.white;
102 _transform = new AffineTransform();
103 _clipTransform = new AffineTransform();
104 _accurateTextMode = true;
105 setColor(Color.black);
106 setPaint(Color.black);
107 setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
108 setFont(Font.decode(null));
109 setStroke(new BasicStroke());
113 * Constructs a new EPS document that is initially empty and can be drawn on
114 * like a Graphics2D object. The EPS document is written to the file as it
115 * goes, which reduces memory usage. The bounding box of the document is fixed
116 * and specified at construction time by minX,minY,maxX,maxY. The file is
117 * flushed and closed when the close() method is called.
119 public EpsGraphics2D(String title, File file, int minX, int minY,
120 int maxX, int maxY) throws IOException
122 this(title, new FileOutputStream(file), minX, minY, maxX, maxY);
126 * Constructs a new EPS document that is initially empty and can be drawn on
127 * like a Graphics2D object. The EPS document is written to the output stream
128 * as it goes, which reduces memory usage. The bounding box of the document is
129 * fixed and specified at construction time by minX,minY,maxX,maxY. The output
130 * stream is flushed and closed when the close() method is called.
132 public EpsGraphics2D(String title, OutputStream outputStream, int minX,
133 int minY, int maxX, int maxY) throws IOException
136 _document = new EpsDocument(title, outputStream, minX, minY, maxX, maxY);
140 * Constructs a new EpsGraphics2D instance that is a copy of the supplied
141 * argument and points at the same EpsDocument.
143 protected EpsGraphics2D(EpsGraphics2D g)
145 _document = g._document;
146 _backgroundColor = g._backgroundColor;
148 _clipTransform = (AffineTransform) g._clipTransform.clone();
149 _transform = (AffineTransform) g._transform.clone();
152 _composite = g._composite;
155 _accurateTextMode = g._accurateTextMode;
159 * This method is called to indicate that a particular method is not supported
160 * yet. The stack trace is printed to the standard output.
162 private void methodNotSupported()
164 EpsException e = new EpsException(
165 "Method not currently supported by EpsGraphics2D version "
167 e.printStackTrace(System.err);
170 // ///////////// Specialist methods ///////////////////////
173 * Sets whether to use accurate text mode when rendering text in EPS. This is
174 * enabled (true) by default. When accurate text mode is used, all text will
175 * be rendered in EPS to appear exactly the same as it would do when drawn
176 * with a Graphics2D context. With accurate text mode enabled, it is not
177 * necessary for the EPS viewer to have the required font installed.
179 * Turning off accurate text mode will require the EPS viewer to have the
180 * necessary fonts installed. If you are using a lot of text, you will find
181 * that this significantly reduces the file size of your EPS documents.
182 * AffineTransforms can only affect the starting point of text using this
183 * simpler text mode - all text will be horizontal.
185 public void setAccurateTextMode(boolean b)
187 _accurateTextMode = b;
191 * Returns whether accurate text mode is being used.
193 public boolean getAccurateTextMode()
195 return _accurateTextMode;
199 * Flushes the buffered contents of this EPS document to the underlying
200 * OutputStream it is being written to.
202 public void flush() throws IOException
208 * Closes the EPS file being output to the underlying OutputStream. The
209 * OutputStream is automatically flushed before being closed. If you forget to
210 * do this, the file may be incomplete.
212 public void close() throws IOException
219 * Appends a line to the EpsDocument.
221 private void append(String line)
223 _document.append(this, line);
227 * Returns the point after it has been transformed by the transformation.
229 private Point2D transform(float x, float y)
231 Point2D result = new Point2D.Float(x, y);
232 result = _transform.transform(result, result);
233 result.setLocation(result.getX(), -result.getY());
238 * Appends the commands required to draw a shape on the EPS document.
240 private void draw(Shape s, String action)
246 // Rectangle2D userBounds = s.getBounds2D();
247 if (!_transform.isIdentity())
249 s = _transform.createTransformedShape(s);
252 // Update the bounds.
253 if (!action.equals("clip"))
255 Rectangle2D shapeBounds = s.getBounds2D();
256 Rectangle2D visibleBounds = shapeBounds;
259 Rectangle2D clipBounds = _clip.getBounds2D();
260 visibleBounds = shapeBounds.createIntersection(clipBounds);
262 float lineRadius = _stroke.getLineWidth() / 2;
263 float minX = (float) visibleBounds.getMinX() - lineRadius;
264 float minY = (float) visibleBounds.getMinY() - lineRadius;
265 float maxX = (float) visibleBounds.getMaxX() + lineRadius;
266 float maxY = (float) visibleBounds.getMaxY() + lineRadius;
267 _document.updateBounds(minX, -minY);
268 _document.updateBounds(maxX, -maxY);
273 float[] coords = new float[6];
274 PathIterator it = s.getPathIterator(null);
280 type = it.currentSegment(coords);
281 float x1 = coords[0];
282 float y1 = -coords[1];
283 float x2 = coords[2];
284 float y2 = -coords[3];
285 float x3 = coords[4];
286 float y3 = -coords[5];
288 if (type == PathIterator.SEG_CLOSE)
293 else if (type == PathIterator.SEG_CUBICTO)
295 append(x1 + " " + y1 + " " + x2 + " " + y2 + " " + x3 + " " + y3
301 else if (type == PathIterator.SEG_LINETO)
303 append(x1 + " " + y1 + " lineto");
308 else if (type == PathIterator.SEG_MOVETO)
310 append(x1 + " " + y1 + " moveto");
315 else if (type == PathIterator.SEG_QUADTO)
317 // Convert the quad curve into a cubic.
318 float _x1 = x0 + 2 / 3f * (x1 - x0);
319 float _y1 = y0 + 2 / 3f * (y1 - y0);
320 float _x2 = x1 + 1 / 3f * (x2 - x1);
321 float _y2 = y1 + 1 / 3f * (y2 - y1);
324 append(_x1 + " " + _y1 + " " + _x2 + " " + _y2 + " " + _x3 + " "
330 else if (type == PathIterator.WIND_EVEN_ODD)
334 else if (type == PathIterator.WIND_NON_ZERO)
346 * Returns a hex string that always contains two characters.
348 private String toHexString(int n)
350 String result = Integer.toString(n, 16);
351 while (result.length() < 2)
353 result = "0" + result;
358 // ///////////// Graphics2D methods ///////////////////////
361 * Draws a 3D rectangle outline. If it is raised, light appears to come from
364 public void draw3DRect(int x, int y, int width, int height, boolean raised)
366 Color originalColor = getColor();
367 Stroke originalStroke = getStroke();
369 setStroke(new BasicStroke(1.0f));
373 setColor(originalColor.brighter());
377 setColor(originalColor.darker());
380 drawLine(x, y, x + width, y);
381 drawLine(x, y, x, y + height);
385 setColor(originalColor.darker());
389 setColor(originalColor.brighter());
392 drawLine(x + width, y + height, x, y + height);
393 drawLine(x + width, y + height, x + width, y);
395 setColor(originalColor);
396 setStroke(originalStroke);
400 * Fills a 3D rectangle. If raised, it has bright fill and light appears to
401 * come from the top left.
403 public void fill3DRect(int x, int y, int width, int height, boolean raised)
405 Color originalColor = getColor();
409 setColor(originalColor.brighter());
413 setColor(originalColor.darker());
415 draw(new Rectangle(x, y, width, height), "fill");
416 setColor(originalColor);
417 draw3DRect(x, y, width, height, raised);
421 * Draws a Shape on the EPS document.
423 public void draw(Shape s)
429 * Draws an Image on the EPS document.
431 public boolean drawImage(Image img, AffineTransform xform,
434 AffineTransform at = getTransform();
436 boolean st = drawImage(img, 0, 0, obs);
442 * Draws a BufferedImage on the EPS document.
444 public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y)
446 BufferedImage img1 = op.filter(img, null);
447 drawImage(img1, new AffineTransform(1f, 0f, 0f, 1f, x, y), null);
451 * Draws a RenderedImage on the EPS document.
453 public void drawRenderedImage(RenderedImage img, AffineTransform xform)
455 Hashtable properties = new Hashtable();
456 String[] names = img.getPropertyNames();
457 for (int i = 0; i < names.length; i++)
459 properties.put(names[i], img.getProperty(names[i]));
462 ColorModel cm = img.getColorModel();
463 WritableRaster wr = img.copyData(null);
464 BufferedImage img1 = new BufferedImage(cm, wr, cm
465 .isAlphaPremultiplied(), properties);
466 AffineTransform at = AffineTransform.getTranslateInstance(
467 img.getMinX(), img.getMinY());
468 at.preConcatenate(xform);
469 drawImage(img1, at, null);
473 * Draws a RenderableImage by invoking its createDefaultRendering method.
475 public void drawRenderableImage(RenderableImage img, AffineTransform xform)
477 drawRenderedImage(img.createDefaultRendering(), xform);
481 * Draws a string at (x,y)
483 public void drawString(String str, int x, int y)
485 drawString(str, (float) x, (float) y);
489 * Draws a string at (x,y)
491 public void drawString(String s, float x, float y)
493 if (s != null && s.length() > 0)
495 AttributedString as = new AttributedString(s);
496 as.addAttribute(TextAttribute.FONT, getFont());
497 drawString(as.getIterator(), x, y);
502 * Draws the characters of an AttributedCharacterIterator, starting from
505 public void drawString(AttributedCharacterIterator iterator, int x, int y)
507 drawString(iterator, (float) x, (float) y);
511 * Draws the characters of an AttributedCharacterIterator, starting from
514 public void drawString(AttributedCharacterIterator iterator, float x,
517 if (getAccurateTextMode())
519 TextLayout layout = new TextLayout(iterator, getFontRenderContext());
520 Shape shape = layout.getOutline(AffineTransform.getTranslateInstance(
527 Point2D location = transform(x, y);
528 append(location.getX() + " " + location.getY() + " moveto");
529 StringBuffer buffer = new StringBuffer();
530 for (char ch = iterator.first(); ch != CharacterIterator.DONE; ch = iterator
533 if (ch == '(' || ch == ')')
539 append("(" + buffer.toString() + ") show");
544 * Draws a GlyphVector at (x,y)
546 public void drawGlyphVector(GlyphVector g, float x, float y)
548 Shape shape = g.getOutline(x, y);
553 * Fills a Shape on the EPS document.
555 public void fill(Shape s)
561 * Checks whether or not the specified Shape intersects the specified
562 * Rectangle, which is in device space.
564 public boolean hit(Rectangle rect, Shape s, boolean onStroke)
566 return s.intersects(rect);
570 * Returns the device configuration associated with this EpsGraphics2D object.
572 public GraphicsConfiguration getDeviceConfiguration()
574 GraphicsConfiguration gc = null;
575 GraphicsEnvironment ge = GraphicsEnvironment
576 .getLocalGraphicsEnvironment();
577 GraphicsDevice[] gds = ge.getScreenDevices();
578 for (int i = 0; i < gds.length; i++)
580 GraphicsDevice gd = gds[i];
581 GraphicsConfiguration[] gcs = gd.getConfigurations();
591 * Sets the Composite to be used by this EpsGraphics2D. EpsGraphics2D does not
594 public void setComposite(Composite comp)
600 * Sets the Paint attribute for the EpsGraphics2D object. Only Paint objects
601 * of type Color are respected by EpsGraphics2D.
603 public void setPaint(Paint paint)
606 if (paint instanceof Color)
608 setColor((Color) paint);
613 * Sets the stroke. Only accepts BasicStroke objects (or subclasses of
616 public void setStroke(Stroke s)
618 if (s instanceof BasicStroke)
620 _stroke = (BasicStroke) s;
622 append(_stroke.getLineWidth() + " setlinewidth");
623 float miterLimit = _stroke.getMiterLimit();
624 if (miterLimit < 1.0f)
628 append(miterLimit + " setmiterlimit");
629 append(_stroke.getLineJoin() + " setlinejoin");
630 append(_stroke.getEndCap() + " setlinecap");
632 StringBuffer dashes = new StringBuffer();
634 float[] dashArray = _stroke.getDashArray();
635 if (dashArray != null)
637 for (int i = 0; i < dashArray.length; i++)
639 dashes.append((dashArray[i]) + " ");
643 append(dashes.toString() + " 0 setdash");
648 * Sets a rendering hint. These are not used by EpsGraphics2D.
650 public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue)
656 * Returns the value of a single preference for the rendering algorithms.
657 * Rendering hints are not used by EpsGraphics2D.
659 public Object getRenderingHint(RenderingHints.Key hintKey)
665 * Sets the rendering hints. These are ignored by EpsGraphics2D.
667 public void setRenderingHints(Map hints)
673 * Adds rendering hints. These are ignored by EpsGraphics2D.
675 public void addRenderingHints(Map hints)
681 * Returns the preferences for the rendering algorithms.
683 public RenderingHints getRenderingHints()
685 return new RenderingHints(null);
689 * Translates the origin of the EpsGraphics2D context to the point (x,y) in
690 * the current coordinate system.
692 public void translate(int x, int y)
694 translate((double) x, (double) y);
698 * Concatenates the current EpsGraphics2D Transformation with a translation
701 public void translate(double tx, double ty)
703 transform(AffineTransform.getTranslateInstance(tx, ty));
707 * Concatenates the current EpsGraphics2D Transform with a rotation transform.
709 public void rotate(double theta)
715 * Concatenates the current EpsGraphics2D Transform with a translated rotation
718 public void rotate(double theta, double x, double y)
720 transform(AffineTransform.getRotateInstance(theta, x, y));
724 * Concatenates the current EpsGraphics2D Transform with a scaling
727 public void scale(double sx, double sy)
729 transform(AffineTransform.getScaleInstance(sx, sy));
733 * Concatenates the current EpsGraphics2D Transform with a shearing transform.
735 public void shear(double shx, double shy)
737 transform(AffineTransform.getShearInstance(shx, shy));
741 * Composes an AffineTransform object with the Transform in this EpsGraphics2D
742 * according to the rule last-specified-first-applied.
744 public void transform(AffineTransform Tx)
746 _transform.concatenate(Tx);
747 setTransform(getTransform());
751 * Sets the AffineTransform to be used by this EpsGraphics2D.
753 public void setTransform(AffineTransform Tx)
757 _transform = new AffineTransform();
761 _transform = new AffineTransform(Tx);
763 // Need to update the stroke and font so they know the scale changed
764 setStroke(getStroke());
769 * Gets the AffineTransform used by this EpsGraphics2D.
771 public AffineTransform getTransform()
773 return new AffineTransform(_transform);
777 * Returns the current Paint of the EpsGraphics2D object.
779 public Paint getPaint()
785 * returns the current Composite of the EpsGraphics2D object.
787 public Composite getComposite()
793 * Sets the background color to be used by the clearRect method.
795 public void setBackground(Color color)
801 _backgroundColor = color;
805 * Gets the background color that is used by the clearRect method.
807 public Color getBackground()
809 return _backgroundColor;
813 * Returns the Stroke currently used. Guaranteed to be an instance of
816 public Stroke getStroke()
822 * Intersects the current clip with the interior of the specified Shape and
823 * sets the clip to the resulting intersection.
825 public void clip(Shape s)
833 Area area = new Area(_clip);
834 area.intersect(new Area(s));
840 * Returns the FontRenderContext.
842 public FontRenderContext getFontRenderContext()
844 return _fontRenderContext;
847 // ///////////// Graphics methods ///////////////////////
850 * Returns a new Graphics object that is identical to this EpsGraphics2D.
852 public Graphics create()
854 return new EpsGraphics2D(this);
858 * Returns an EpsGraphics2D object based on this Graphics object, but with a
859 * new translation and clip area.
861 public Graphics create(int x, int y, int width, int height)
863 Graphics g = create();
865 g.clipRect(0, 0, width, height);
870 * Returns the current Color. This will be a default value (black) until it is
871 * changed using the setColor method.
873 public Color getColor()
879 * Sets the Color to be used when drawing all future shapes, text, etc.
881 public void setColor(Color c)
888 append((c.getRed() / 255f) + " " + (c.getGreen() / 255f) + " "
889 + (c.getBlue() / 255f) + " setrgbcolor");
893 * Sets the paint mode of this EpsGraphics2D object to overwrite the
894 * destination EpsDocument with the current color.
896 public void setPaintMode()
898 // Do nothing - paint mode is the only method supported anyway.
902 * <b><i><font color="red">Not implemented</font></i></b> - performs no
905 public void setXORMode(Color c1)
907 methodNotSupported();
911 * Returns the Font currently being used.
913 public Font getFont()
919 * Sets the Font to be used in future text.
921 public void setFont(Font font)
925 font = Font.decode(null);
928 append("/" + _font.getPSName() + " findfont " + ((int) _font.getSize())
929 + " scalefont setfont");
933 * Gets the font metrics of the current font.
935 public FontMetrics getFontMetrics()
937 return getFontMetrics(getFont());
941 * Gets the font metrics for the specified font.
943 public FontMetrics getFontMetrics(Font f)
945 BufferedImage image = new BufferedImage(1, 1,
946 BufferedImage.TYPE_INT_RGB);
947 Graphics g = image.getGraphics();
948 return g.getFontMetrics(f);
952 * Returns the bounding rectangle of the current clipping area.
954 public Rectangle getClipBounds()
960 Rectangle rect = getClip().getBounds();
965 * Intersects the current clip with the specified rectangle.
967 public void clipRect(int x, int y, int width, int height)
969 clip(new Rectangle(x, y, width, height));
973 * Sets the current clip to the rectangle specified by the given coordinates.
975 public void setClip(int x, int y, int width, int height)
977 setClip(new Rectangle(x, y, width, height));
981 * Gets the current clipping area.
983 public Shape getClip()
993 AffineTransform t = _transform.createInverse();
994 t.concatenate(_clipTransform);
995 return t.createTransformedShape(_clip);
996 } catch (Exception e)
998 throw new EpsException("Unable to get inverse of matrix: "
1005 * Sets the current clipping area to an arbitrary clip shape.
1007 public void setClip(Shape clip)
1011 if (_document.isClipSet())
1018 _document.setClipSet(true);
1023 _clipTransform = (AffineTransform) _transform.clone();
1027 if (_document.isClipSet())
1030 _document.setClipSet(false);
1037 * <b><i><font color="red">Not implemented</font></i></b> - performs no
1040 public void copyArea(int x, int y, int width, int height, int dx, int dy)
1042 methodNotSupported();
1046 * Draws a straight line from (x1,y1) to (x2,y2).
1048 public void drawLine(int x1, int y1, int x2, int y2)
1050 Shape shape = new Line2D.Float(x1, y1, x2, y2);
1055 * Fills a rectangle with top-left corner placed at (x,y).
1057 public void fillRect(int x, int y, int width, int height)
1059 Shape shape = new Rectangle(x, y, width, height);
1060 draw(shape, "fill");
1064 * Draws a rectangle with top-left corner placed at (x,y).
1066 public void drawRect(int x, int y, int width, int height)
1068 Shape shape = new Rectangle(x, y, width, height);
1073 * Clears a rectangle with top-left corner placed at (x,y) using the current
1076 public void clearRect(int x, int y, int width, int height)
1078 Color originalColor = getColor();
1080 setColor(getBackground());
1081 Shape shape = new Rectangle(x, y, width, height);
1082 draw(shape, "fill");
1084 setColor(originalColor);
1088 * Draws a rounded rectangle.
1090 public void drawRoundRect(int x, int y, int width, int height,
1091 int arcWidth, int arcHeight)
1093 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
1099 * Fills a rounded rectangle.
1101 public void fillRoundRect(int x, int y, int width, int height,
1102 int arcWidth, int arcHeight)
1104 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
1106 draw(shape, "fill");
1112 public void drawOval(int x, int y, int width, int height)
1114 Shape shape = new Ellipse2D.Float(x, y, width, height);
1121 public void fillOval(int x, int y, int width, int height)
1123 Shape shape = new Ellipse2D.Float(x, y, width, height);
1124 draw(shape, "fill");
1130 public void drawArc(int x, int y, int width, int height, int startAngle,
1133 Shape shape = new Arc2D.Float(x, y, width, height, startAngle,
1134 arcAngle, Arc2D.OPEN);
1141 public void fillArc(int x, int y, int width, int height, int startAngle,
1144 Shape shape = new Arc2D.Float(x, y, width, height, startAngle,
1145 arcAngle, Arc2D.PIE);
1146 draw(shape, "fill");
1152 public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
1156 GeneralPath path = new GeneralPath();
1157 path.moveTo(xPoints[0], yPoints[0]);
1158 for (int i = 1; i < nPoints; i++)
1160 path.lineTo(xPoints[i], yPoints[i]);
1167 * Draws a polygon made with the specified points.
1169 public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
1171 Shape shape = new Polygon(xPoints, yPoints, nPoints);
1178 public void drawPolygon(Polygon p)
1184 * Fills a polygon made with the specified points.
1186 public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
1188 Shape shape = new Polygon(xPoints, yPoints, nPoints);
1189 draw(shape, "fill");
1195 public void fillPolygon(Polygon p)
1201 * Draws the specified characters, starting from (x,y)
1203 public void drawChars(char[] data, int offset, int length, int x, int y)
1205 String string = new String(data, offset, length);
1206 drawString(string, x, y);
1210 * Draws the specified bytes, starting from (x,y)
1212 public void drawBytes(byte[] data, int offset, int length, int x, int y)
1214 String string = new String(data, offset, length);
1215 drawString(string, x, y);
1221 public boolean drawImage(Image img, int x, int y, ImageObserver observer)
1223 return drawImage(img, x, y, Color.white, observer);
1229 public boolean drawImage(Image img, int x, int y, int width, int height,
1230 ImageObserver observer)
1232 return drawImage(img, x, y, width, height, Color.white, observer);
1238 public boolean drawImage(Image img, int x, int y, Color bgcolor,
1239 ImageObserver observer)
1241 int width = img.getWidth(null);
1242 int height = img.getHeight(null);
1243 return drawImage(img, x, y, width, height, bgcolor, observer);
1249 public boolean drawImage(Image img, int x, int y, int width, int height,
1250 Color bgcolor, ImageObserver observer)
1252 return drawImage(img, x, y, x + width, y + height, 0, 0, width, height,
1259 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
1260 int sx1, int sy1, int sx2, int sy2, ImageObserver observer)
1262 return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1263 Color.white, observer);
1269 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
1270 int sx1, int sy1, int sx2, int sy2, Color bgcolor,
1271 ImageObserver observer)
1275 throw new IllegalArgumentException("dx1 >= dx2");
1279 throw new IllegalArgumentException("sx1 >= sx2");
1283 throw new IllegalArgumentException("dy1 >= dy2");
1287 throw new IllegalArgumentException("sy1 >= sy2");
1292 int width = sx2 - sx1;
1293 int height = sy2 - sy1;
1294 int destWidth = dx2 - dx1;
1295 int destHeight = dy2 - dy1;
1297 int[] pixels = new int[width * height];
1298 PixelGrabber pg = new PixelGrabber(img, sx1, sy1, sx2 - sx1, sy2 - sy1,
1303 } catch (InterruptedException e)
1308 AffineTransform matrix = new AffineTransform(_transform);
1309 matrix.translate(dx1, dy1);
1310 matrix.scale(destWidth / (double) width, destHeight / (double) height);
1311 double[] m = new double[6];
1314 matrix = matrix.createInverse();
1315 } catch (Exception e)
1317 throw new EpsException("Unable to get inverse of matrix: " + matrix);
1319 matrix.scale(1, -1);
1320 matrix.getMatrix(m);
1321 append(width + " " + height + " 8 [" + m[0] + " " + m[1] + " " + m[2]
1322 + " " + m[3] + " " + m[4] + " " + m[5] + "]");
1323 // Fill the background to update the bounding box.
1324 Color oldColor = getColor();
1325 setColor(getBackground());
1326 fillRect(dx1, dy1, destWidth, destHeight);
1328 append("{currentfile 3 " + width
1329 + " mul string readhexstring pop} bind");
1330 append("false 3 colorimage");
1331 StringBuffer line = new StringBuffer();
1332 for (int y = 0; y < height; y++)
1334 for (int x = 0; x < width; x++)
1336 Color color = new Color(pixels[x + width * y]);
1337 line.append(toHexString(color.getRed())
1338 + toHexString(color.getGreen())
1339 + toHexString(color.getBlue()));
1340 if (line.length() > 64)
1342 append(line.toString());
1343 line = new StringBuffer();
1347 if (line.length() > 0)
1349 append(line.toString());
1358 * Disposes of all resources used by this EpsGraphics2D object. If this is the
1359 * only remaining EpsGraphics2D instance pointing at a EpsDocument object,
1360 * then the EpsDocument object shall become eligible for garbage collection.
1362 public void dispose()
1368 * Finalizes the object.
1370 public void finalize()
1376 * Returns the entire contents of the EPS document, complete with headers and
1377 * bounding box. The returned String is suitable for being written directly to
1378 * disk as an EPS file.
1380 public String toString()
1382 StringWriter writer = new StringWriter();
1385 _document.write(writer);
1388 } catch (IOException e)
1390 throw new EpsException(e.toString());
1392 return writer.toString();
1396 * Returns true if the specified rectangular area might intersect the current
1399 public boolean hitClip(int x, int y, int width, int height)
1405 Rectangle rect = new Rectangle(x, y, width, height);
1406 return hit(rect, _clip, true);
1410 * Returns the bounding rectangle of the current clipping area.
1412 public Rectangle getClipBounds(Rectangle r)
1418 Rectangle rect = getClipBounds();
1419 r.setLocation((int) rect.getX(), (int) rect.getY());
1420 r.setSize((int) rect.getWidth(), (int) rect.getHeight());
1424 private Color _color;
1426 private Color _backgroundColor;
1428 private Paint _paint;
1430 private Composite _composite;
1432 private BasicStroke _stroke;
1436 private Shape _clip;
1438 private AffineTransform _clipTransform;
1440 private AffineTransform _transform;
1442 private boolean _accurateTextMode;
1444 private EpsDocument _document;
1446 private static FontRenderContext _fontRenderContext = new FontRenderContext(