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;
23 import jalview.util.MessageManager;
30 import java.awt.font.*;
31 import java.awt.geom.*;
32 import java.awt.image.*;
33 import java.awt.image.renderable.*;
36 * EpsGraphics2D is suitable for creating high quality EPS graphics for use in
37 * documents and papers, and can be used just like a standard Graphics2D object.
39 * Many Java programs use Graphics2D to draw stuff on the screen, and while it
40 * is easy to save the output as a png or jpeg file, it is a little harder to
41 * export it as an EPS for including in a document or paper.
43 * This class makes the whole process extremely easy, because you can use it as
44 * if it's a Graphics2D object. The only difference is that all of the
45 * implemented methods create EPS output, which means the diagrams you draw can
46 * be resized without leading to any of the jagged edges you may see when
47 * resizing pixel-based images, such as jpeg and png files.
53 * Graphics2D g = new EpsGraphics2D();
54 * g.setColor(Color.black);
56 * // Line thickness 2.
57 * g.setStroke(new BasicStroke(2.0f));
60 * g.drawLine(10, 10, 50, 10);
62 * // Fill a rectangle in blue
63 * g.setColor(Color.blue);
64 * g.fillRect(10, 0, 20, 20);
66 * // Get the EPS output.
67 * String output = g.toString();
71 * You do not need to worry about the size of the canvas when drawing on a
72 * EpsGraphics2D object. The bounding box of the EPS document will automatically
73 * resize to accomodate new items that you draw.
75 * Not all methods are implemented yet. Those that are not are clearly labelled.
77 * Copyright Paul Mutton, <a
78 * href="http://www.jibble.org/">http://www.jibble.org/</a>
81 public class EpsGraphics2D extends java.awt.Graphics2D
84 public static final String VERSION = "0.8.8";
87 * Constructs a new EPS document that is initially empty and can be drawn on
88 * like a Graphics2D object. The EPS document is stored in memory.
90 public EpsGraphics2D()
96 * Constructs a new EPS document that is initially empty and can be drawn on
97 * like a Graphics2D object. The EPS document is stored in memory.
99 public EpsGraphics2D(String title)
101 _document = new EpsDocument(title);
102 _backgroundColor = Color.white;
104 _transform = new AffineTransform();
105 _clipTransform = new AffineTransform();
106 _accurateTextMode = true;
107 setColor(Color.black);
108 setPaint(Color.black);
109 setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
110 setFont(Font.decode(null));
111 setStroke(new BasicStroke());
115 * Constructs a new EPS document that is initially empty and can be drawn on
116 * like a Graphics2D object. The EPS document is written to the file as it
117 * goes, which reduces memory usage. The bounding box of the document is fixed
118 * and specified at construction time by minX,minY,maxX,maxY. The file is
119 * flushed and closed when the close() method is called.
121 public EpsGraphics2D(String title, File file, int minX, int minY,
122 int maxX, int maxY) throws IOException
124 this(title, new FileOutputStream(file), minX, minY, maxX, maxY);
128 * Constructs a new EPS document that is initially empty and can be drawn on
129 * like a Graphics2D object. The EPS document is written to the output stream
130 * as it goes, which reduces memory usage. The bounding box of the document is
131 * fixed and specified at construction time by minX,minY,maxX,maxY. The output
132 * stream is flushed and closed when the close() method is called.
134 public EpsGraphics2D(String title, OutputStream outputStream, int minX,
135 int minY, int maxX, int maxY) throws IOException
138 _document = new EpsDocument(title, outputStream, minX, minY, maxX, maxY);
142 * Constructs a new EpsGraphics2D instance that is a copy of the supplied
143 * argument and points at the same EpsDocument.
145 protected EpsGraphics2D(EpsGraphics2D g)
147 _document = g._document;
148 _backgroundColor = g._backgroundColor;
150 _clipTransform = (AffineTransform) g._clipTransform.clone();
151 _transform = (AffineTransform) g._transform.clone();
154 _composite = g._composite;
157 _accurateTextMode = g._accurateTextMode;
161 * This method is called to indicate that a particular method is not supported
162 * yet. The stack trace is printed to the standard output.
164 private void methodNotSupported()
166 EpsException e = new EpsException(MessageManager.formatMessage("exception.eps_method_not_supported", new String[]{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(MessageManager.formatMessage("exception.eps_unable_to_get_inverse_matrix", new String[]{_transform.toString()}));
1004 * Sets the current clipping area to an arbitrary clip shape.
1006 public void setClip(Shape clip)
1010 if (_document.isClipSet())
1017 _document.setClipSet(true);
1022 _clipTransform = (AffineTransform) _transform.clone();
1026 if (_document.isClipSet())
1029 _document.setClipSet(false);
1036 * <b><i><font color="red">Not implemented</font></i></b> - performs no
1039 public void copyArea(int x, int y, int width, int height, int dx, int dy)
1041 methodNotSupported();
1045 * Draws a straight line from (x1,y1) to (x2,y2).
1047 public void drawLine(int x1, int y1, int x2, int y2)
1049 Shape shape = new Line2D.Float(x1, y1, x2, y2);
1054 * Fills a rectangle with top-left corner placed at (x,y).
1056 public void fillRect(int x, int y, int width, int height)
1058 Shape shape = new Rectangle(x, y, width, height);
1059 draw(shape, "fill");
1063 * Draws a rectangle with top-left corner placed at (x,y).
1065 public void drawRect(int x, int y, int width, int height)
1067 Shape shape = new Rectangle(x, y, width, height);
1072 * Clears a rectangle with top-left corner placed at (x,y) using the current
1075 public void clearRect(int x, int y, int width, int height)
1077 Color originalColor = getColor();
1079 setColor(getBackground());
1080 Shape shape = new Rectangle(x, y, width, height);
1081 draw(shape, "fill");
1083 setColor(originalColor);
1087 * Draws a rounded rectangle.
1089 public void drawRoundRect(int x, int y, int width, int height,
1090 int arcWidth, int arcHeight)
1092 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
1098 * Fills a rounded rectangle.
1100 public void fillRoundRect(int x, int y, int width, int height,
1101 int arcWidth, int arcHeight)
1103 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
1105 draw(shape, "fill");
1111 public void drawOval(int x, int y, int width, int height)
1113 Shape shape = new Ellipse2D.Float(x, y, width, height);
1120 public void fillOval(int x, int y, int width, int height)
1122 Shape shape = new Ellipse2D.Float(x, y, width, height);
1123 draw(shape, "fill");
1129 public void drawArc(int x, int y, int width, int height, int startAngle,
1132 Shape shape = new Arc2D.Float(x, y, width, height, startAngle,
1133 arcAngle, Arc2D.OPEN);
1140 public void fillArc(int x, int y, int width, int height, int startAngle,
1143 Shape shape = new Arc2D.Float(x, y, width, height, startAngle,
1144 arcAngle, Arc2D.PIE);
1145 draw(shape, "fill");
1151 public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
1155 GeneralPath path = new GeneralPath();
1156 path.moveTo(xPoints[0], yPoints[0]);
1157 for (int i = 1; i < nPoints; i++)
1159 path.lineTo(xPoints[i], yPoints[i]);
1166 * Draws a polygon made with the specified points.
1168 public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
1170 Shape shape = new Polygon(xPoints, yPoints, nPoints);
1177 public void drawPolygon(Polygon p)
1183 * Fills a polygon made with the specified points.
1185 public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
1187 Shape shape = new Polygon(xPoints, yPoints, nPoints);
1188 draw(shape, "fill");
1194 public void fillPolygon(Polygon p)
1200 * Draws the specified characters, starting from (x,y)
1202 public void drawChars(char[] data, int offset, int length, int x, int y)
1204 String string = new String(data, offset, length);
1205 drawString(string, x, y);
1209 * Draws the specified bytes, starting from (x,y)
1211 public void drawBytes(byte[] data, int offset, int length, int x, int y)
1213 String string = new String(data, offset, length);
1214 drawString(string, x, y);
1220 public boolean drawImage(Image img, int x, int y, ImageObserver observer)
1222 return drawImage(img, x, y, Color.white, observer);
1228 public boolean drawImage(Image img, int x, int y, int width, int height,
1229 ImageObserver observer)
1231 return drawImage(img, x, y, width, height, Color.white, observer);
1237 public boolean drawImage(Image img, int x, int y, Color bgcolor,
1238 ImageObserver observer)
1240 int width = img.getWidth(null);
1241 int height = img.getHeight(null);
1242 return drawImage(img, x, y, width, height, bgcolor, observer);
1248 public boolean drawImage(Image img, int x, int y, int width, int height,
1249 Color bgcolor, ImageObserver observer)
1251 return drawImage(img, x, y, x + width, y + height, 0, 0, width, height,
1258 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
1259 int sx1, int sy1, int sx2, int sy2, ImageObserver observer)
1261 return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1262 Color.white, observer);
1268 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
1269 int sx1, int sy1, int sx2, int sy2, Color bgcolor,
1270 ImageObserver observer)
1274 throw new IllegalArgumentException("dx1 >= dx2");
1278 throw new IllegalArgumentException("sx1 >= sx2");
1282 throw new IllegalArgumentException("dy1 >= dy2");
1286 throw new IllegalArgumentException("sy1 >= sy2");
1291 int width = sx2 - sx1;
1292 int height = sy2 - sy1;
1293 int destWidth = dx2 - dx1;
1294 int destHeight = dy2 - dy1;
1296 int[] pixels = new int[width * height];
1297 PixelGrabber pg = new PixelGrabber(img, sx1, sy1, sx2 - sx1, sy2 - sy1,
1302 } catch (InterruptedException e)
1307 AffineTransform matrix = new AffineTransform(_transform);
1308 matrix.translate(dx1, dy1);
1309 matrix.scale(destWidth / (double) width, destHeight / (double) height);
1310 double[] m = new double[6];
1313 matrix = matrix.createInverse();
1314 } catch (Exception e)
1316 throw new EpsException(MessageManager.formatMessage("exception.eps_unable_to_get_inverse_matrix", new String[]{matrix.toString()}));
1318 matrix.scale(1, -1);
1319 matrix.getMatrix(m);
1320 append(width + " " + height + " 8 [" + m[0] + " " + m[1] + " " + m[2]
1321 + " " + m[3] + " " + m[4] + " " + m[5] + "]");
1322 // Fill the background to update the bounding box.
1323 Color oldColor = getColor();
1324 setColor(getBackground());
1325 fillRect(dx1, dy1, destWidth, destHeight);
1327 append("{currentfile 3 " + width
1328 + " mul string readhexstring pop} bind");
1329 append("false 3 colorimage");
1330 StringBuffer line = new StringBuffer();
1331 for (int y = 0; y < height; y++)
1333 for (int x = 0; x < width; x++)
1335 Color color = new Color(pixels[x + width * y]);
1336 line.append(toHexString(color.getRed())
1337 + toHexString(color.getGreen())
1338 + toHexString(color.getBlue()));
1339 if (line.length() > 64)
1341 append(line.toString());
1342 line = new StringBuffer();
1346 if (line.length() > 0)
1348 append(line.toString());
1357 * Disposes of all resources used by this EpsGraphics2D object. If this is the
1358 * only remaining EpsGraphics2D instance pointing at a EpsDocument object,
1359 * then the EpsDocument object shall become eligible for garbage collection.
1361 public void dispose()
1367 * Finalizes the object.
1369 public void finalize()
1375 * Returns the entire contents of the EPS document, complete with headers and
1376 * bounding box. The returned String is suitable for being written directly to
1377 * disk as an EPS file.
1379 public String toString()
1381 StringWriter writer = new StringWriter();
1384 _document.write(writer);
1387 } catch (IOException e)
1389 throw new EpsException(e.toString());
1391 return writer.toString();
1395 * Returns true if the specified rectangular area might intersect the current
1398 public boolean hitClip(int x, int y, int width, int height)
1404 Rectangle rect = new Rectangle(x, y, width, height);
1405 return hit(rect, _clip, true);
1409 * Returns the bounding rectangle of the current clipping area.
1411 public Rectangle getClipBounds(Rectangle r)
1417 Rectangle rect = getClipBounds();
1418 r.setLocation((int) rect.getX(), (int) rect.getY());
1419 r.setSize((int) rect.getWidth(), (int) rect.getHeight());
1423 private Color _color;
1425 private Color _backgroundColor;
1427 private Paint _paint;
1429 private Composite _composite;
1431 private BasicStroke _stroke;
1435 private Shape _clip;
1437 private AffineTransform _clipTransform;
1439 private AffineTransform _transform;
1441 private boolean _accurateTextMode;
1443 private EpsDocument _document;
1445 private static FontRenderContext _fontRenderContext = new FontRenderContext(