2 Copyright Paul James Mutton, 2001-2004, http://www.jibble.org/
\r
4 This file is part of EpsGraphics2D.
\r
6 This software is dual-licensed, allowing you to choose between the GNU
\r
7 General Public License (GPL) and the www.jibble.org Commercial License.
\r
8 Since the GPL may be too restrictive for use in a proprietary application,
\r
9 a commercial license is also provided. Full license information can be
\r
10 found at http://www.jibble.org/licenses/
\r
17 package org.jibble.epsgraphics;
\r
24 import java.awt.font.*;
\r
25 import java.awt.geom.*;
\r
26 import java.awt.image.*;
\r
27 import java.awt.image.renderable.*;
\r
30 * EpsGraphics2D is suitable for creating high quality EPS graphics for
\r
31 * use in documents and papers, and can be used just like a standard
\r
32 * Graphics2D object.
\r
34 * Many Java programs use Graphics2D to draw stuff on the screen, and while
\r
35 * it is easy to save the output as a png or jpeg file, it is a little
\r
36 * harder to export it as an EPS for including in a document or paper.
\r
38 * This class makes the whole process extremely easy, because you can use
\r
39 * it as if it's a Graphics2D object. The only difference is that all of
\r
40 * the implemented methods create EPS output, which means the diagrams you
\r
41 * draw can be resized without leading to any of the jagged edges you may
\r
42 * see when resizing pixel-based images, such as jpeg and png files.
\r
46 * <pre> Graphics2D g = new EpsGraphics2D();
\r
47 * g.setColor(Color.black);
\r
49 * // Line thickness 2.
\r
50 * g.setStroke(new BasicStroke(2.0f));
\r
53 * g.drawLine(10, 10, 50, 10);
\r
55 * // Fill a rectangle in blue
\r
56 * g.setColor(Color.blue);
\r
57 * g.fillRect(10, 0, 20, 20);
\r
59 * // Get the EPS output.
\r
60 * String output = g.toString();</pre>
\r
62 * You do not need to worry about the size of the canvas when drawing on a
\r
63 * EpsGraphics2D object. The bounding box of the EPS document will
\r
64 * automatically resize to accomodate new items that you draw.
\r
66 * Not all methods are implemented yet. Those that are not are clearly
\r
69 * Copyright Paul Mutton,
\r
70 * <a href="http://www.jibble.org/">http://www.jibble.org/</a>
\r
73 public class EpsGraphics2D
\r
74 extends java.awt.Graphics2D
\r
77 public static final String VERSION = "0.8.8";
\r
80 * Constructs a new EPS document that is initially empty and can be
\r
81 * drawn on like a Graphics2D object. The EPS document is stored in
\r
84 public EpsGraphics2D()
\r
90 * Constructs a new EPS document that is initially empty and can be
\r
91 * drawn on like a Graphics2D object. The EPS document is stored in
\r
94 public EpsGraphics2D(String title)
\r
96 _document = new EpsDocument(title);
\r
97 _backgroundColor = Color.white;
\r
99 _transform = new AffineTransform();
\r
100 _clipTransform = new AffineTransform();
\r
101 _accurateTextMode = true;
\r
102 setColor(Color.black);
\r
103 setPaint(Color.black);
\r
104 setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
\r
105 setFont(Font.decode(null));
\r
106 setStroke(new BasicStroke());
\r
110 * Constructs a new EPS document that is initially empty and can be
\r
111 * drawn on like a Graphics2D object. The EPS document is written to
\r
112 * the file as it goes, which reduces memory usage. The bounding box of
\r
113 * the document is fixed and specified at construction time by
\r
114 * minX,minY,maxX,maxY. The file is flushed and closed when the close()
\r
115 * method is called.
\r
117 public EpsGraphics2D(String title, File file, int minX, int minY, int maxX,
\r
121 this(title, new FileOutputStream(file), minX, minY, maxX, maxY);
\r
125 * Constructs a new EPS document that is initially empty and can be
\r
126 * drawn on like a Graphics2D object. The EPS document is written to
\r
127 * the output stream as it goes, which reduces memory usage. The
\r
128 * bounding box of the document is fixed and specified at construction
\r
129 * time by minX,minY,maxX,maxY. The output stream is flushed and closed
\r
130 * when the close() method is called.
\r
132 public EpsGraphics2D(String title, OutputStream outputStream, int minX,
\r
133 int minY, int maxX, int maxY)
\r
137 _document = new EpsDocument(title, outputStream, minX, minY, maxX, maxY);
\r
141 * Constructs a new EpsGraphics2D instance that is a copy of the
\r
142 * supplied argument and points at the same EpsDocument.
\r
144 protected EpsGraphics2D(EpsGraphics2D g)
\r
146 _document = g._document;
\r
147 _backgroundColor = g._backgroundColor;
\r
149 _clipTransform = (AffineTransform) g._clipTransform.clone();
\r
150 _transform = (AffineTransform) g._transform.clone();
\r
153 _composite = g._composite;
\r
155 _stroke = g._stroke;
\r
156 _accurateTextMode = g._accurateTextMode;
\r
160 * This method is called to indicate that a particular method is not
\r
161 * supported yet. The stack trace is printed to the standard output.
\r
163 private void methodNotSupported()
\r
165 EpsException e = new EpsException(
\r
166 "Method not currently supported by EpsGraphics2D version " + VERSION);
\r
167 e.printStackTrace(System.err);
\r
170 /////////////// Specialist methods ///////////////////////
\r
174 * Sets whether to use accurate text mode when rendering text in EPS.
\r
175 * This is enabled (true) by default. When accurate text mode is used,
\r
176 * all text will be rendered in EPS to appear exactly the same as it
\r
177 * would do when drawn with a Graphics2D context. With accurate text
\r
178 * mode enabled, it is not necessary for the EPS viewer to have the
\r
179 * required font installed.
\r
181 * Turning off accurate text mode will require the EPS viewer to have
\r
182 * the necessary fonts installed. If you are using a lot of text, you
\r
183 * will find that this significantly reduces the file size of your EPS
\r
184 * documents. AffineTransforms can only affect the starting point of
\r
185 * text using this simpler text mode - all text will be horizontal.
\r
187 public void setAccurateTextMode(boolean b)
\r
189 _accurateTextMode = b;
\r
193 * Returns whether accurate text mode is being used.
\r
195 public boolean getAccurateTextMode()
\r
197 return _accurateTextMode;
\r
201 * Flushes the buffered contents of this EPS document to the underlying
\r
202 * OutputStream it is being written to.
\r
204 public void flush()
\r
211 * Closes the EPS file being output to the underlying OutputStream.
\r
212 * The OutputStream is automatically flushed before being closed.
\r
213 * If you forget to do this, the file may be incomplete.
\r
215 public void close()
\r
223 * Appends a line to the EpsDocument.
\r
225 private void append(String line)
\r
227 _document.append(this, line);
\r
231 * Returns the point after it has been transformed by the transformation.
\r
233 private Point2D transform(float x, float y)
\r
235 Point2D result = new Point2D.Float(x, y);
\r
236 result = _transform.transform(result, result);
\r
237 result.setLocation(result.getX(), -result.getY());
\r
242 * Appends the commands required to draw a shape on the EPS document.
\r
244 private void draw(Shape s, String action)
\r
250 //Rectangle2D userBounds = s.getBounds2D();
\r
251 if (!_transform.isIdentity())
\r
253 s = _transform.createTransformedShape(s);
\r
256 // Update the bounds.
\r
257 if (!action.equals("clip"))
\r
259 Rectangle2D shapeBounds = s.getBounds2D();
\r
260 Rectangle2D visibleBounds = shapeBounds;
\r
263 Rectangle2D clipBounds = _clip.getBounds2D();
\r
264 visibleBounds = shapeBounds.createIntersection(clipBounds);
\r
266 float lineRadius = _stroke.getLineWidth() / 2;
\r
267 float minX = (float) visibleBounds.getMinX() - lineRadius;
\r
268 float minY = (float) visibleBounds.getMinY() - lineRadius;
\r
269 float maxX = (float) visibleBounds.getMaxX() + lineRadius;
\r
270 float maxY = (float) visibleBounds.getMaxY() + lineRadius;
\r
271 _document.updateBounds(minX, -minY);
\r
272 _document.updateBounds(maxX, -maxY);
\r
277 float[] coords = new float[6];
\r
278 PathIterator it = s.getPathIterator(null);
\r
282 while (!it.isDone())
\r
284 type = it.currentSegment(coords);
\r
285 float x1 = coords[0];
\r
286 float y1 = -coords[1];
\r
287 float x2 = coords[2];
\r
288 float y2 = -coords[3];
\r
289 float x3 = coords[4];
\r
290 float y3 = -coords[5];
\r
292 if (type == PathIterator.SEG_CLOSE)
\r
294 append("closepath");
\r
297 else if (type == PathIterator.SEG_CUBICTO)
\r
299 append(x1 + " " + y1 + " " + x2 + " " + y2 + " " + x3 + " " + y3 +
\r
305 else if (type == PathIterator.SEG_LINETO)
\r
307 append(x1 + " " + y1 + " lineto");
\r
312 else if (type == PathIterator.SEG_MOVETO)
\r
314 append(x1 + " " + y1 + " moveto");
\r
319 else if (type == PathIterator.SEG_QUADTO)
\r
321 // Convert the quad curve into a cubic.
\r
322 float _x1 = x0 + 2 / 3f * (x1 - x0);
\r
323 float _y1 = y0 + 2 / 3f * (y1 - y0);
\r
324 float _x2 = x1 + 1 / 3f * (x2 - x1);
\r
325 float _y2 = y1 + 1 / 3f * (y2 - y1);
\r
328 append(_x1 + " " + _y1 + " " + _x2 + " " + _y2 + " " + _x3 + " " +
\r
334 else if (type == PathIterator.WIND_EVEN_ODD)
\r
338 else if (type == PathIterator.WIND_NON_ZERO)
\r
350 * Returns a hex string that always contains two characters.
\r
352 private String toHexString(int n)
\r
354 String result = Integer.toString(n, 16);
\r
355 while (result.length() < 2)
\r
357 result = "0" + result;
\r
362 /////////////// Graphics2D methods ///////////////////////
\r
366 * Draws a 3D rectangle outline. If it is raised, light appears to come
\r
367 * from the top left.
\r
369 public void draw3DRect(int x, int y, int width, int height, boolean raised)
\r
371 Color originalColor = getColor();
\r
372 Stroke originalStroke = getStroke();
\r
374 setStroke(new BasicStroke(1.0f));
\r
378 setColor(originalColor.brighter());
\r
382 setColor(originalColor.darker());
\r
385 drawLine(x, y, x + width, y);
\r
386 drawLine(x, y, x, y + height);
\r
390 setColor(originalColor.darker());
\r
394 setColor(originalColor.brighter());
\r
397 drawLine(x + width, y + height, x, y + height);
\r
398 drawLine(x + width, y + height, x + width, y);
\r
400 setColor(originalColor);
\r
401 setStroke(originalStroke);
\r
405 * Fills a 3D rectangle. If raised, it has bright fill and light appears
\r
406 * to come from the top left.
\r
408 public void fill3DRect(int x, int y, int width, int height, boolean raised)
\r
410 Color originalColor = getColor();
\r
414 setColor(originalColor.brighter());
\r
418 setColor(originalColor.darker());
\r
420 draw(new Rectangle(x, y, width, height), "fill");
\r
421 setColor(originalColor);
\r
422 draw3DRect(x, y, width, height, raised);
\r
426 * Draws a Shape on the EPS document.
\r
428 public void draw(Shape s)
\r
434 * Draws an Image on the EPS document.
\r
436 public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
\r
438 AffineTransform at = getTransform();
\r
440 boolean st = drawImage(img, 0, 0, obs);
\r
446 * Draws a BufferedImage on the EPS document.
\r
448 public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y)
\r
450 BufferedImage img1 = op.filter(img, null);
\r
451 drawImage(img1, new AffineTransform(1f, 0f, 0f, 1f, x, y), null);
\r
455 * Draws a RenderedImage on the EPS document.
\r
457 public void drawRenderedImage(RenderedImage img, AffineTransform xform)
\r
459 Hashtable properties = new Hashtable();
\r
460 String[] names = img.getPropertyNames();
\r
461 for (int i = 0; i < names.length; i++)
\r
463 properties.put(names[i], img.getProperty(names[i]));
\r
466 ColorModel cm = img.getColorModel();
\r
467 WritableRaster wr = img.copyData(null);
\r
468 BufferedImage img1 = new BufferedImage(cm, wr, cm.isAlphaPremultiplied(),
\r
470 AffineTransform at = AffineTransform.getTranslateInstance(img.getMinX(),
\r
472 at.preConcatenate(xform);
\r
473 drawImage(img1, at, null);
\r
477 * Draws a RenderableImage by invoking its createDefaultRendering method.
\r
479 public void drawRenderableImage(RenderableImage img, AffineTransform xform)
\r
481 drawRenderedImage(img.createDefaultRendering(), xform);
\r
485 * Draws a string at (x,y)
\r
487 public void drawString(String str, int x, int y)
\r
489 drawString(str, (float) x, (float) y);
\r
493 * Draws a string at (x,y)
\r
495 public void drawString(String s, float x, float y)
\r
497 if (s != null && s.length() > 0)
\r
499 AttributedString as = new AttributedString(s);
\r
500 as.addAttribute(TextAttribute.FONT, getFont());
\r
501 drawString(as.getIterator(), x, y);
\r
506 * Draws the characters of an AttributedCharacterIterator, starting from
\r
509 public void drawString(AttributedCharacterIterator iterator, int x, int y)
\r
511 drawString(iterator, (float) x, (float) y);
\r
515 * Draws the characters of an AttributedCharacterIterator, starting from
\r
518 public void drawString(AttributedCharacterIterator iterator, float x, float y)
\r
520 if (getAccurateTextMode())
\r
522 TextLayout layout = new TextLayout(iterator, getFontRenderContext());
\r
523 Shape shape = layout.getOutline(AffineTransform.getTranslateInstance(x, y));
\r
524 draw(shape, "fill");
\r
529 Point2D location = transform(x, y);
\r
530 append(location.getX() + " " + location.getY() + " moveto");
\r
531 StringBuffer buffer = new StringBuffer();
\r
532 for (char ch = iterator.first(); ch != CharacterIterator.DONE;
\r
533 ch = iterator.next())
\r
535 if (ch == '(' || ch == ')')
\r
537 buffer.append('\\');
\r
541 append("(" + buffer.toString() + ") show");
\r
546 * Draws a GlyphVector at (x,y)
\r
548 public void drawGlyphVector(GlyphVector g, float x, float y)
\r
550 Shape shape = g.getOutline(x, y);
\r
551 draw(shape, "fill");
\r
555 * Fills a Shape on the EPS document.
\r
557 public void fill(Shape s)
\r
563 * Checks whether or not the specified Shape intersects the specified
\r
564 * Rectangle, which is in device space.
\r
566 public boolean hit(Rectangle rect, Shape s, boolean onStroke)
\r
568 return s.intersects(rect);
\r
572 * Returns the device configuration associated with this EpsGraphics2D
\r
575 public GraphicsConfiguration getDeviceConfiguration()
\r
577 GraphicsConfiguration gc = null;
\r
578 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
\r
579 GraphicsDevice[] gds = ge.getScreenDevices();
\r
580 for (int i = 0; i < gds.length; i++)
\r
582 GraphicsDevice gd = gds[i];
\r
583 GraphicsConfiguration[] gcs = gd.getConfigurations();
\r
584 if (gcs.length > 0)
\r
593 * Sets the Composite to be used by this EpsGraphics2D. EpsGraphics2D
\r
594 * does not make use of these.
\r
596 public void setComposite(Composite comp)
\r
602 * Sets the Paint attribute for the EpsGraphics2D object. Only Paint
\r
603 * objects of type Color are respected by EpsGraphics2D.
\r
605 public void setPaint(Paint paint)
\r
608 if (paint instanceof Color)
\r
610 setColor( (Color) paint);
\r
615 * Sets the stroke. Only accepts BasicStroke objects (or subclasses of
\r
618 public void setStroke(Stroke s)
\r
620 if (s instanceof BasicStroke)
\r
622 _stroke = (BasicStroke) s;
\r
624 append(_stroke.getLineWidth() + " setlinewidth");
\r
625 float miterLimit = _stroke.getMiterLimit();
\r
626 if (miterLimit < 1.0f)
\r
630 append(miterLimit + " setmiterlimit");
\r
631 append(_stroke.getLineJoin() + " setlinejoin");
\r
632 append(_stroke.getEndCap() + " setlinecap");
\r
634 StringBuffer dashes = new StringBuffer();
\r
635 dashes.append("[ ");
\r
636 float[] dashArray = _stroke.getDashArray();
\r
637 if (dashArray != null)
\r
639 for (int i = 0; i < dashArray.length; i++)
\r
641 dashes.append( (dashArray[i]) + " ");
\r
644 dashes.append("]");
\r
645 append(dashes.toString() + " 0 setdash");
\r
650 * Sets a rendering hint. These are not used by EpsGraphics2D.
\r
652 public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue)
\r
658 * Returns the value of a single preference for the rendering
\r
659 * algorithms. Rendering hints are not used by EpsGraphics2D.
\r
661 public Object getRenderingHint(RenderingHints.Key hintKey)
\r
667 * Sets the rendering hints. These are ignored by EpsGraphics2D.
\r
669 public void setRenderingHints(Map hints)
\r
675 * Adds rendering hints. These are ignored by EpsGraphics2D.
\r
677 public void addRenderingHints(Map hints)
\r
683 * Returns the preferences for the rendering algorithms.
\r
685 public RenderingHints getRenderingHints()
\r
687 return new RenderingHints(null);
\r
691 * Translates the origin of the EpsGraphics2D context to the point (x,y)
\r
692 * in the current coordinate system.
\r
694 public void translate(int x, int y)
\r
696 translate( (double) x, (double) y);
\r
700 * Concatenates the current EpsGraphics2D Transformation with a
\r
701 * translation transform.
\r
703 public void translate(double tx, double ty)
\r
705 transform(AffineTransform.getTranslateInstance(tx, ty));
\r
709 * Concatenates the current EpsGraphics2D Transform with a rotation
\r
712 public void rotate(double theta)
\r
714 rotate(theta, 0, 0);
\r
718 * Concatenates the current EpsGraphics2D Transform with a translated
\r
719 * rotation transform.
\r
721 public void rotate(double theta, double x, double y)
\r
723 transform(AffineTransform.getRotateInstance(theta, x, y));
\r
727 * Concatenates the current EpsGraphics2D Transform with a scaling
\r
730 public void scale(double sx, double sy)
\r
732 transform(AffineTransform.getScaleInstance(sx, sy));
\r
736 * Concatenates the current EpsGraphics2D Transform with a shearing
\r
739 public void shear(double shx, double shy)
\r
741 transform(AffineTransform.getShearInstance(shx, shy));
\r
745 * Composes an AffineTransform object with the Transform in this
\r
746 * EpsGraphics2D according to the rule last-specified-first-applied.
\r
748 public void transform(AffineTransform Tx)
\r
750 _transform.concatenate(Tx);
\r
751 setTransform(getTransform());
\r
755 * Sets the AffineTransform to be used by this EpsGraphics2D.
\r
757 public void setTransform(AffineTransform Tx)
\r
761 _transform = new AffineTransform();
\r
765 _transform = new AffineTransform(Tx);
\r
767 // Need to update the stroke and font so they know the scale changed
\r
768 setStroke(getStroke());
\r
769 setFont(getFont());
\r
773 * Gets the AffineTransform used by this EpsGraphics2D.
\r
775 public AffineTransform getTransform()
\r
777 return new AffineTransform(_transform);
\r
781 * Returns the current Paint of the EpsGraphics2D object.
\r
783 public Paint getPaint()
\r
789 * returns the current Composite of the EpsGraphics2D object.
\r
791 public Composite getComposite()
\r
797 * Sets the background color to be used by the clearRect method.
\r
799 public void setBackground(Color color)
\r
803 color = Color.black;
\r
805 _backgroundColor = color;
\r
809 * Gets the background color that is used by the clearRect method.
\r
811 public Color getBackground()
\r
813 return _backgroundColor;
\r
817 * Returns the Stroke currently used. Guaranteed to be an instance of
\r
820 public Stroke getStroke()
\r
826 * Intersects the current clip with the interior of the specified Shape
\r
827 * and sets the clip to the resulting intersection.
\r
829 public void clip(Shape s)
\r
837 Area area = new Area(_clip);
\r
838 area.intersect(new Area(s));
\r
844 * Returns the FontRenderContext.
\r
846 public FontRenderContext getFontRenderContext()
\r
848 return _fontRenderContext;
\r
851 /////////////// Graphics methods ///////////////////////
\r
855 * Returns a new Graphics object that is identical to this EpsGraphics2D.
\r
857 public Graphics create()
\r
859 return new EpsGraphics2D(this);
\r
863 * Returns an EpsGraphics2D object based on this
\r
864 * Graphics object, but with a new translation and clip
\r
867 public Graphics create(int x, int y, int width, int height)
\r
869 Graphics g = create();
\r
871 g.clipRect(0, 0, width, height);
\r
876 * Returns the current Color. This will be a default value (black)
\r
877 * until it is changed using the setColor method.
\r
879 public Color getColor()
\r
885 * Sets the Color to be used when drawing all future shapes, text, etc.
\r
887 public void setColor(Color c)
\r
894 append( (c.getRed() / 255f) + " " + (c.getGreen() / 255f) + " " +
\r
895 (c.getBlue() / 255f) + " setrgbcolor");
\r
899 * Sets the paint mode of this EpsGraphics2D object to overwrite the
\r
900 * destination EpsDocument with the current color.
\r
902 public void setPaintMode()
\r
904 // Do nothing - paint mode is the only method supported anyway.
\r
908 * <b><i><font color="red">Not implemented</font></i></b> - performs no action.
\r
910 public void setXORMode(Color c1)
\r
912 methodNotSupported();
\r
916 * Returns the Font currently being used.
\r
918 public Font getFont()
\r
924 * Sets the Font to be used in future text.
\r
926 public void setFont(Font font)
\r
930 font = Font.decode(null);
\r
933 append("/" + _font.getPSName() + " findfont " + ( (int) _font.getSize()) +
\r
934 " scalefont setfont");
\r
938 * Gets the font metrics of the current font.
\r
940 public FontMetrics getFontMetrics()
\r
942 return getFontMetrics(getFont());
\r
946 * Gets the font metrics for the specified font.
\r
948 public FontMetrics getFontMetrics(Font f)
\r
950 BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
\r
951 Graphics g = image.getGraphics();
\r
952 return g.getFontMetrics(f);
\r
956 * Returns the bounding rectangle of the current clipping area.
\r
958 public Rectangle getClipBounds()
\r
964 Rectangle rect = getClip().getBounds();
\r
969 * Intersects the current clip with the specified rectangle.
\r
971 public void clipRect(int x, int y, int width, int height)
\r
973 clip(new Rectangle(x, y, width, height));
\r
977 * Sets the current clip to the rectangle specified by the given
\r
980 public void setClip(int x, int y, int width, int height)
\r
982 setClip(new Rectangle(x, y, width, height));
\r
986 * Gets the current clipping area.
\r
988 public Shape getClip()
\r
998 AffineTransform t = _transform.createInverse();
\r
999 t.concatenate(_clipTransform);
\r
1000 return t.createTransformedShape(_clip);
\r
1002 catch (Exception e)
\r
1004 throw new EpsException("Unable to get inverse of matrix: " + _transform);
\r
1010 * Sets the current clipping area to an arbitrary clip shape.
\r
1012 public void setClip(Shape clip)
\r
1016 if (_document.isClipSet())
\r
1018 append("grestore");
\r
1023 _document.setClipSet(true);
\r
1026 draw(clip, "clip");
\r
1028 _clipTransform = (AffineTransform) _transform.clone();
\r
1032 if (_document.isClipSet())
\r
1034 append("grestore");
\r
1035 _document.setClipSet(false);
\r
1042 * <b><i><font color="red">Not implemented</font></i></b> - performs no action.
\r
1044 public void copyArea(int x, int y, int width, int height, int dx, int dy)
\r
1046 methodNotSupported();
\r
1050 * Draws a straight line from (x1,y1) to (x2,y2).
\r
1052 public void drawLine(int x1, int y1, int x2, int y2)
\r
1054 Shape shape = new Line2D.Float(x1, y1, x2, y2);
\r
1059 * Fills a rectangle with top-left corner placed at (x,y).
\r
1061 public void fillRect(int x, int y, int width, int height)
\r
1063 Shape shape = new Rectangle(x, y, width, height);
\r
1064 draw(shape, "fill");
\r
1068 * Draws a rectangle with top-left corner placed at (x,y).
\r
1070 public void drawRect(int x, int y, int width, int height)
\r
1072 Shape shape = new Rectangle(x, y, width, height);
\r
1077 * Clears a rectangle with top-left corner placed at (x,y) using the
\r
1078 * current background color.
\r
1080 public void clearRect(int x, int y, int width, int height)
\r
1082 Color originalColor = getColor();
\r
1084 setColor(getBackground());
\r
1085 Shape shape = new Rectangle(x, y, width, height);
\r
1086 draw(shape, "fill");
\r
1088 setColor(originalColor);
\r
1092 * Draws a rounded rectangle.
\r
1094 public void drawRoundRect(int x, int y, int width, int height, int arcWidth,
\r
1097 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
\r
1103 * Fills a rounded rectangle.
\r
1105 public void fillRoundRect(int x, int y, int width, int height, int arcWidth,
\r
1108 Shape shape = new RoundRectangle2D.Float(x, y, width, height, arcWidth,
\r
1110 draw(shape, "fill");
\r
1116 public void drawOval(int x, int y, int width, int height)
\r
1118 Shape shape = new Ellipse2D.Float(x, y, width, height);
\r
1125 public void fillOval(int x, int y, int width, int height)
\r
1127 Shape shape = new Ellipse2D.Float(x, y, width, height);
\r
1128 draw(shape, "fill");
\r
1134 public void drawArc(int x, int y, int width, int height, int startAngle,
\r
1137 Shape shape = new Arc2D.Float(x, y, width, height, startAngle, arcAngle,
\r
1145 public void fillArc(int x, int y, int width, int height, int startAngle,
\r
1148 Shape shape = new Arc2D.Float(x, y, width, height, startAngle, arcAngle,
\r
1150 draw(shape, "fill");
\r
1154 * Draws a polyline.
\r
1156 public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints)
\r
1160 GeneralPath path = new GeneralPath();
\r
1161 path.moveTo(xPoints[0], yPoints[0]);
\r
1162 for (int i = 1; i < nPoints; i++)
\r
1164 path.lineTo(xPoints[i], yPoints[i]);
\r
1171 * Draws a polygon made with the specified points.
\r
1173 public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)
\r
1175 Shape shape = new Polygon(xPoints, yPoints, nPoints);
\r
1180 * Draws a polygon.
\r
1182 public void drawPolygon(Polygon p)
\r
1188 * Fills a polygon made with the specified points.
\r
1190 public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints)
\r
1192 Shape shape = new Polygon(xPoints, yPoints, nPoints);
\r
1193 draw(shape, "fill");
\r
1197 * Fills a polygon.
\r
1199 public void fillPolygon(Polygon p)
\r
1205 * Draws the specified characters, starting from (x,y)
\r
1207 public void drawChars(char[] data, int offset, int length, int x, int y)
\r
1209 String string = new String(data, offset, length);
\r
1210 drawString(string, x, y);
\r
1214 * Draws the specified bytes, starting from (x,y)
\r
1216 public void drawBytes(byte[] data, int offset, int length, int x, int y)
\r
1218 String string = new String(data, offset, length);
\r
1219 drawString(string, x, y);
\r
1225 public boolean drawImage(Image img, int x, int y, ImageObserver observer)
\r
1227 return drawImage(img, x, y, Color.white, observer);
\r
1233 public boolean drawImage(Image img, int x, int y, int width, int height,
\r
1234 ImageObserver observer)
\r
1236 return drawImage(img, x, y, width, height, Color.white, observer);
\r
1242 public boolean drawImage(Image img, int x, int y, Color bgcolor,
\r
1243 ImageObserver observer)
\r
1245 int width = img.getWidth(null);
\r
1246 int height = img.getHeight(null);
\r
1247 return drawImage(img, x, y, width, height, bgcolor, observer);
\r
1253 public boolean drawImage(Image img, int x, int y, int width, int height,
\r
1254 Color bgcolor, ImageObserver observer)
\r
1256 return drawImage(img, x, y, x + width, y + height, 0, 0, width, height,
\r
1257 bgcolor, observer);
\r
1263 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
\r
1264 int sx1, int sy1, int sx2, int sy2,
\r
1265 ImageObserver observer)
\r
1267 return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, Color.white,
\r
1274 public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2,
\r
1275 int sx1, int sy1, int sx2, int sy2, Color bgcolor,
\r
1276 ImageObserver observer)
\r
1280 throw new IllegalArgumentException("dx1 >= dx2");
\r
1284 throw new IllegalArgumentException("sx1 >= sx2");
\r
1288 throw new IllegalArgumentException("dy1 >= dy2");
\r
1292 throw new IllegalArgumentException("sy1 >= sy2");
\r
1297 int width = sx2 - sx1;
\r
1298 int height = sy2 - sy1;
\r
1299 int destWidth = dx2 - dx1;
\r
1300 int destHeight = dy2 - dy1;
\r
1302 int[] pixels = new int[width * height];
\r
1303 PixelGrabber pg = new PixelGrabber(img, sx1, sy1, sx2 - sx1, sy2 - sy1,
\r
1304 pixels, 0, width);
\r
1309 catch (InterruptedException e)
\r
1314 AffineTransform matrix = new AffineTransform(_transform);
\r
1315 matrix.translate(dx1, dy1);
\r
1316 matrix.scale(destWidth / (double) width, destHeight / (double) height);
\r
1317 double[] m = new double[6];
\r
1320 matrix = matrix.createInverse();
\r
1322 catch (Exception e)
\r
1324 throw new EpsException("Unable to get inverse of matrix: " + matrix);
\r
1326 matrix.scale(1, -1);
\r
1327 matrix.getMatrix(m);
\r
1328 append(width + " " + height + " 8 [" + m[0] + " " + m[1] + " " + m[2] + " " +
\r
1329 m[3] + " " + m[4] + " " + m[5] + "]");
\r
1330 // Fill the background to update the bounding box.
\r
1331 Color oldColor = getColor();
\r
1332 setColor(getBackground());
\r
1333 fillRect(dx1, dy1, destWidth, destHeight);
\r
1334 setColor(oldColor);
\r
1335 append("{currentfile 3 " + width + " mul string readhexstring pop} bind");
\r
1336 append("false 3 colorimage");
\r
1337 StringBuffer line = new StringBuffer();
\r
1338 for (int y = 0; y < height; y++)
\r
1340 for (int x = 0; x < width; x++)
\r
1342 Color color = new Color(pixels[x + width * y]);
\r
1343 line.append(toHexString(color.getRed()) + toHexString(color.getGreen()) +
\r
1344 toHexString(color.getBlue()));
\r
1345 if (line.length() > 64)
\r
1347 append(line.toString());
\r
1348 line = new StringBuffer();
\r
1352 if (line.length() > 0)
\r
1354 append(line.toString());
\r
1357 append("grestore");
\r
1363 * Disposes of all resources used by this EpsGraphics2D object.
\r
1364 * If this is the only remaining EpsGraphics2D instance pointing at
\r
1365 * a EpsDocument object, then the EpsDocument object shall become
\r
1366 * eligible for garbage collection.
\r
1368 public void dispose()
\r
1374 * Finalizes the object.
\r
1376 public void finalize()
\r
1382 * Returns the entire contents of the EPS document, complete with
\r
1383 * headers and bounding box. The returned String is suitable for
\r
1384 * being written directly to disk as an EPS file.
\r
1386 public String toString()
\r
1388 StringWriter writer = new StringWriter();
\r
1391 _document.write(writer);
\r
1392 _document.flush();
\r
1393 _document.close();
\r
1395 catch (IOException e)
\r
1397 throw new EpsException(e.toString());
\r
1399 return writer.toString();
\r
1403 * Returns true if the specified rectangular area might intersect the
\r
1404 * current clipping area.
\r
1406 public boolean hitClip(int x, int y, int width, int height)
\r
1408 if (_clip == null)
\r
1412 Rectangle rect = new Rectangle(x, y, width, height);
\r
1413 return hit(rect, _clip, true);
\r
1417 * Returns the bounding rectangle of the current clipping area.
\r
1419 public Rectangle getClipBounds(Rectangle r)
\r
1421 if (_clip == null)
\r
1425 Rectangle rect = getClipBounds();
\r
1426 r.setLocation( (int) rect.getX(), (int) rect.getY());
\r
1427 r.setSize( (int) rect.getWidth(), (int) rect.getHeight());
\r
1431 private Color _color;
\r
1432 private Color _backgroundColor;
\r
1433 private Paint _paint;
\r
1434 private Composite _composite;
\r
1435 private BasicStroke _stroke;
\r
1436 private Font _font;
\r
1437 private Shape _clip;
\r
1438 private AffineTransform _clipTransform;
\r
1439 private AffineTransform _transform;
\r
1440 private boolean _accurateTextMode;
\r
1442 private EpsDocument _document;
\r
1444 private static FontRenderContext _fontRenderContext = new FontRenderContext(null, false, true);
\r