| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* $Id$ */ |
| |
| package org.apache.xmlgraphics.java2d.ps; |
| |
| //Java |
| import java.awt.AlphaComposite; |
| import java.awt.BasicStroke; |
| import java.awt.Color; |
| import java.awt.Dimension; |
| /* java.awt.Font is not imported to avoid confusion with |
| other classes called "Font" */ |
| import java.awt.GradientPaint; |
| import java.awt.Graphics; |
| import java.awt.Graphics2D; |
| import java.awt.GraphicsConfiguration; |
| import java.awt.GraphicsEnvironment; |
| import java.awt.Image; |
| import java.awt.Paint; |
| import java.awt.Rectangle; |
| import java.awt.Shape; |
| import java.awt.Stroke; |
| import java.awt.TexturePaint; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.PathIterator; |
| import java.awt.image.BufferedImage; |
| import java.awt.image.ImageObserver; |
| import java.awt.image.RenderedImage; |
| import java.awt.image.renderable.RenderableImage; |
| import java.io.IOException; |
| |
| import org.apache.xmlgraphics.java2d.AbstractGraphics2D; |
| import org.apache.xmlgraphics.java2d.GraphicContext; |
| import org.apache.xmlgraphics.java2d.StrokingTextHandler; |
| import org.apache.xmlgraphics.java2d.TextHandler; |
| import org.apache.xmlgraphics.ps.PSGenerator; |
| import org.apache.xmlgraphics.ps.PSImageUtils; |
| |
| /** |
| * This is a concrete implementation of <tt>AbstractGraphics2D</tt> (and |
| * therefore of <tt>Graphics2D</tt>) which is able to generate PostScript |
| * code. |
| * |
| * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a> |
| * @version $Id$ |
| * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D |
| */ |
| public class PSGraphics2D extends AbstractGraphics2D { |
| |
| private static final AffineTransform IDENTITY_TRANSFORM = new AffineTransform(); |
| |
| private static final boolean DEBUG = false; |
| |
| protected PSGraphics2D rootG2D; |
| |
| /** the PostScript generator being created */ |
| protected PSGenerator gen; |
| |
| private boolean clippingDisabled = false; |
| |
| /** Fallback text handler */ |
| protected TextHandler fallbackTextHandler = new StrokingTextHandler(this); |
| |
| /** Custom text handler */ |
| protected TextHandler customTextHandler; |
| |
| /** |
| * the current colour for use in svg |
| */ |
| protected Color currentColour = new Color(0, 0, 0); |
| |
| /** |
| * Create a new Graphics2D that generates PostScript code. |
| * @param textAsShapes True if text should be rendered as graphics |
| * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D#AbstractGraphics2D(boolean) |
| */ |
| public PSGraphics2D(boolean textAsShapes) { |
| super(textAsShapes); |
| } |
| |
| /** |
| * Create a new Graphics2D that generates PostScript code. |
| * @param textAsShapes True if text should be rendered as graphics |
| * @param gen PostScript generator to use for output |
| * @see org.apache.xmlgraphics.java2d.AbstractGraphics2D#AbstractGraphics2D(boolean) |
| */ |
| public PSGraphics2D(boolean textAsShapes, PSGenerator gen) { |
| this(textAsShapes); |
| setPSGenerator(gen); |
| } |
| |
| /** |
| * Constructor for creating copies |
| * @param g parent PostScript Graphics2D |
| */ |
| public PSGraphics2D(PSGraphics2D g) { |
| super(g); |
| |
| this.rootG2D = (g.rootG2D != null ? g.rootG2D : g); |
| setPSGenerator(g.gen); |
| this.clippingDisabled = g.clippingDisabled; |
| this.fallbackTextHandler = g.fallbackTextHandler; |
| this.customTextHandler = g.customTextHandler; |
| this.currentColour = g.currentColour; |
| } |
| |
| /** |
| * Sets the PostScript generator |
| * @param gen the PostScript generator |
| */ |
| public void setPSGenerator(PSGenerator gen) { |
| this.gen = gen; |
| } |
| |
| /** @return the PostScript generator used by this instance. */ |
| public PSGenerator getPSGenerator() { |
| return this.gen; |
| } |
| |
| /** |
| * Sets the GraphicContext |
| * @param c GraphicContext to use |
| */ |
| public void setGraphicContext(GraphicContext c) { |
| gc = c; |
| //setPrivateHints(); |
| } |
| |
| /** @return the fallback TextHandler implementation */ |
| public TextHandler getFallbackTextHandler() { |
| return this.fallbackTextHandler; |
| } |
| |
| /** @return the custom TextHandler implementation */ |
| public TextHandler getCustomTextHandler() { |
| return this.customTextHandler; |
| } |
| |
| /** |
| * Sets a custom TextHandler implementation that is responsible for painting text. The default |
| * TextHandler paints all text as shapes. A custom implementation can implement text painting |
| * using text painting operators. |
| * @param handler the custom TextHandler implementation |
| */ |
| public void setCustomTextHandler(TextHandler handler) { |
| this.customTextHandler = handler; |
| } |
| |
| /* TODO Add me back at the right place!!! |
| private void setPrivateHints() { |
| setRenderingHint(RenderingHintsKeyExt.KEY_AVOID_TILE_PAINTING, |
| RenderingHintsKeyExt.VALUE_AVOID_TILE_PAINTING_ON); |
| }*/ |
| |
| /** |
| * Creates a new <code>Graphics</code> object that is |
| * a copy of this <code>Graphics</code> object. |
| * @return a new graphics context that is a copy of |
| * this graphics context. |
| */ |
| public Graphics create() { |
| preparePainting(); |
| return new PSGraphics2D(this); |
| } |
| |
| /** |
| * Central handler for IOExceptions for this class. |
| * @param ioe IOException to handle |
| */ |
| public void handleIOException(IOException ioe) { |
| //TODO Surely, there's a better way to do this. |
| ioe.printStackTrace(); |
| } |
| |
| /** |
| * This method is used by AbstractPSDocumentGraphics2D to prepare a new page if |
| * necessary. |
| */ |
| public void preparePainting() { |
| //nop, used by AbstractPSDocumentGraphics2D |
| if (rootG2D != null) { |
| rootG2D.preparePainting(); |
| } |
| } |
| |
| /** |
| * Draws as much of the specified image as is currently available. |
| * The image is drawn with its top-left corner at |
| * (<i>x</i>, <i>y</i>) in this graphics context's coordinate |
| * space. Transparent pixels in the image do not affect whatever |
| * pixels are already there. |
| * <p> |
| * This method returns immediately in all cases, even if the |
| * complete image has not yet been loaded, and it has not been dithered |
| * and converted for the current output device. |
| * <p> |
| * If the image has not yet been completely loaded, then |
| * <code>drawImage</code> returns <code>false</code>. As more of |
| * the image becomes available, the process that draws the image notifies |
| * the specified image observer. |
| * @param img the specified image to be drawn. |
| * @param x the <i>x</i> coordinate. |
| * @param y the <i>y</i> coordinate. |
| * @param observer object to be notified as more of |
| * the image is converted. |
| * @return True if the image has been fully drawn/loaded |
| * @see java.awt.Image |
| * @see java.awt.image.ImageObserver |
| * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) |
| */ |
| public boolean drawImage(Image img, int x, int y, |
| ImageObserver observer) { |
| preparePainting(); |
| if (DEBUG) { |
| System.out.println("drawImage: " + x + ", " + y + " " + img.getClass().getName()); |
| } |
| |
| final int width = img.getWidth(observer); |
| final int height = img.getHeight(observer); |
| if (width == -1 || height == -1) { |
| return false; |
| } |
| |
| Dimension size = new Dimension(width, height); |
| BufferedImage buf = buildBufferedImage(size); |
| |
| java.awt.Graphics2D g = buf.createGraphics(); |
| g.setComposite(AlphaComposite.SrcOver); |
| g.setBackground(new Color(1, 1, 1, 0)); |
| g.setPaint(new Color(1, 1, 1, 0)); |
| g.fillRect(0, 0, width, height); |
| g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight())); |
| |
| if (!g.drawImage(img, 0, 0, observer)) { |
| return false; |
| } |
| g.dispose(); |
| |
| try { |
| AffineTransform at = getTransform(); |
| gen.saveGraphicsState(); |
| gen.concatMatrix(at); |
| Shape imclip = getClip(); |
| writeClip(imclip); |
| PSImageUtils.renderBitmapImage(buf, |
| x, y, width, height, gen); |
| gen.restoreGraphicsState(); |
| } catch (IOException ioe) { |
| handleIOException(ioe); |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Creates a buffered image. |
| * @param size dimensions of the image to be created |
| * @return the buffered image |
| */ |
| public BufferedImage buildBufferedImage(Dimension size) { |
| return new BufferedImage(size.width, size.height, |
| BufferedImage.TYPE_INT_ARGB); |
| } |
| |
| /** |
| * Draws as much of the specified image as has already been scaled |
| * to fit inside the specified rectangle. |
| * <p> |
| * The image is drawn inside the specified rectangle of this |
| * graphics context's coordinate space, and is scaled if |
| * necessary. Transparent pixels do not affect whatever pixels |
| * are already there. |
| * <p> |
| * This method returns immediately in all cases, even if the |
| * entire image has not yet been scaled, dithered, and converted |
| * for the current output device. |
| * If the current output representation is not yet complete, then |
| * <code>drawImage</code> returns <code>false</code>. As more of |
| * the image becomes available, the process that draws the image notifies |
| * the image observer by calling its <code>imageUpdate</code> method. |
| * <p> |
| * A scaled version of an image will not necessarily be |
| * available immediately just because an unscaled version of the |
| * image has been constructed for this output device. Each size of |
| * the image may be cached separately and generated from the original |
| * data in a separate image production sequence. |
| * @param img the specified image to be drawn. |
| * @param x the <i>x</i> coordinate. |
| * @param y the <i>y</i> coordinate. |
| * @param width the width of the rectangle. |
| * @param height the height of the rectangle. |
| * @param observer object to be notified as more of |
| * the image is converted. |
| * @return True if the image has been fully loaded/drawn |
| * @see java.awt.Image |
| * @see java.awt.image.ImageObserver |
| * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int) |
| */ |
| public boolean drawImage(Image img, int x, int y, int width, int height, |
| ImageObserver observer) { |
| preparePainting(); |
| System.err.println("NYI: drawImage"); |
| return true; |
| } |
| |
| /** |
| * Disposes of this graphics context and releases |
| * any system resources that it is using. |
| * A <code>Graphics</code> object cannot be used after |
| * <code>dispose</code>has been called. |
| * <p> |
| * When a Java program runs, a large number of <code>Graphics</code> |
| * objects can be created within a short time frame. |
| * Although the finalization process of the garbage collector |
| * also disposes of the same system resources, it is preferable |
| * to manually free the associated resources by calling this |
| * method rather than to rely on a finalization process which |
| * may not run to completion for a long period of time. |
| * <p> |
| * Graphics objects which are provided as arguments to the |
| * <code>paint</code> and <code>update</code> methods |
| * of components are automatically released by the system when |
| * those methods return. For efficiency, programmers should |
| * call <code>dispose</code> when finished using |
| * a <code>Graphics</code> object only if it was created |
| * directly from a component or another <code>Graphics</code> object. |
| * @see java.awt.Graphics#finalize |
| * @see java.awt.Component#paint |
| * @see java.awt.Component#update |
| * @see java.awt.Component#getGraphics |
| * @see java.awt.Graphics#create |
| */ |
| public void dispose() { |
| this.gen = null; |
| this.fallbackTextHandler = null; |
| this.customTextHandler = null; |
| this.currentColour = null; |
| } |
| |
| /** |
| * Processes a path iterator generating the nexessary painting operations. |
| * @param iter PathIterator to process |
| * @throws IOException In case of an I/O problem. |
| */ |
| public void processPathIterator(PathIterator iter) throws IOException { |
| double[] vals = new double[6]; |
| while (!iter.isDone()) { |
| int type = iter.currentSegment(vals); |
| switch (type) { |
| case PathIterator.SEG_CUBICTO: |
| gen.writeln(gen.formatDouble(vals[0]) + " " |
| + gen.formatDouble(vals[1]) + " " |
| + gen.formatDouble(vals[2]) + " " |
| + gen.formatDouble(vals[3]) + " " |
| + gen.formatDouble(vals[4]) + " " |
| + gen.formatDouble(vals[5]) |
| + " curveto"); |
| break; |
| case PathIterator.SEG_LINETO: |
| gen.writeln(gen.formatDouble(vals[0]) + " " |
| + gen.formatDouble(vals[1]) |
| + " lineto"); |
| break; |
| case PathIterator.SEG_MOVETO: |
| gen.writeln(gen.formatDouble(vals[0]) + " " |
| + gen.formatDouble(vals[1]) |
| + " M"); |
| break; |
| case PathIterator.SEG_QUADTO: |
| gen.writeln(gen.formatDouble(vals[0]) + " " |
| + gen.formatDouble(vals[1]) + " " |
| + gen.formatDouble(vals[2]) + " " |
| + gen.formatDouble(vals[3]) + " QUADTO "); |
| break; |
| case PathIterator.SEG_CLOSE: |
| gen.writeln("closepath"); |
| break; |
| default: |
| break; |
| } |
| iter.next(); |
| } |
| } |
| |
| /** |
| * Strokes the outline of a <code>Shape</code> using the settings of the |
| * current <code>Graphics2D</code> context. The rendering attributes |
| * applied include the <code>Clip</code>, <code>Transform</code>, |
| * <code>Paint</code>, <code>Composite</code> and |
| * <code>Stroke</code> attributes. |
| * @param s the <code>Shape</code> to be rendered |
| * @see #setStroke |
| * @see #setPaint |
| * @see java.awt.Graphics#setColor |
| * @see #transform |
| * @see #setTransform |
| * @see #clip |
| * @see #setClip |
| * @see #setComposite |
| */ |
| public void draw(Shape s) { |
| preparePainting(); |
| try { |
| gen.saveGraphicsState(); |
| |
| AffineTransform trans = getTransform(); |
| boolean newTransform = gen.getCurrentState().checkTransform(trans) |
| && !trans.isIdentity(); |
| |
| if (newTransform) { |
| gen.concatMatrix(trans); |
| } |
| Shape imclip = getClip(); |
| writeClip(imclip); |
| establishColor(getColor()); |
| |
| applyPaint(getPaint(), false); |
| applyStroke(getStroke()); |
| |
| gen.writeln("newpath"); |
| PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM); |
| processPathIterator(iter); |
| doDrawing(false, true, false); |
| gen.restoreGraphicsState(); |
| } catch (IOException ioe) { |
| handleIOException(ioe); |
| } |
| } |
| |
| /** |
| * Establishes a clipping region |
| * @param s Shape defining the clipping region |
| */ |
| public void writeClip(Shape s) { |
| if (s == null) { |
| return; |
| } |
| if (!this.clippingDisabled) { |
| preparePainting(); |
| try { |
| gen.writeln("newpath"); |
| PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM); |
| processPathIterator(iter); |
| // clip area |
| gen.writeln("clip"); |
| } catch (IOException ioe) { |
| handleIOException(ioe); |
| } |
| } |
| } |
| |
| /** |
| * Applies a new Paint object. |
| * @param paint Paint object to use |
| * @param fill True if to be applied for filling |
| */ |
| protected void applyPaint(Paint paint, boolean fill) { |
| preparePainting(); |
| if (paint instanceof GradientPaint) { |
| System.err.println("NYI: Gradient paint"); |
| } else if (paint instanceof TexturePaint) { |
| System.err.println("NYI: texture paint"); |
| } |
| } |
| |
| /** |
| * Applies a new Stroke object. |
| * @param stroke Stroke object to use |
| */ |
| protected void applyStroke(Stroke stroke) { |
| preparePainting(); |
| try { |
| if (stroke instanceof BasicStroke) { |
| BasicStroke bs = (BasicStroke)stroke; |
| |
| float[] da = bs.getDashArray(); |
| if (da != null) { |
| gen.write("["); |
| for (int count = 0; count < da.length; count++) { |
| gen.write(gen.formatDouble(da[count])); |
| if (count < da.length - 1) { |
| gen.write(" "); |
| } |
| } |
| gen.write("] "); |
| float offset = bs.getDashPhase(); |
| gen.writeln(gen.formatDouble(offset) + " setdash"); |
| } |
| int ec = bs.getEndCap(); |
| switch (ec) { |
| case BasicStroke.CAP_BUTT: |
| gen.writeln("0 setlinecap"); |
| break; |
| case BasicStroke.CAP_ROUND: |
| gen.writeln("1 setlinecap"); |
| break; |
| case BasicStroke.CAP_SQUARE: |
| gen.writeln("2 setlinecap"); |
| break; |
| default: System.err.println("Unsupported line cap: " + ec); |
| } |
| |
| int lj = bs.getLineJoin(); |
| switch (lj) { |
| case BasicStroke.JOIN_MITER: |
| gen.writeln("0 setlinejoin"); |
| float ml = bs.getMiterLimit(); |
| gen.writeln(gen.formatDouble(ml >= -1 ? ml : 1) + " setmiterlimit"); |
| break; |
| case BasicStroke.JOIN_ROUND: |
| gen.writeln("1 setlinejoin"); |
| break; |
| case BasicStroke.JOIN_BEVEL: |
| gen.writeln("2 setlinejoin"); |
| break; |
| default: System.err.println("Unsupported line join: " + lj); |
| } |
| float lw = bs.getLineWidth(); |
| gen.writeln(gen.formatDouble(lw) + " setlinewidth"); |
| } |
| } catch (IOException ioe) { |
| handleIOException(ioe); |
| } |
| } |
| |
| /** |
| * Renders a {@link RenderedImage}, |
| * applying a transform from image |
| * space into user space before drawing. |
| * The transformation from user space into device space is done with |
| * the current <code>Transform</code> in the <code>Graphics2D</code>. |
| * The specified transformation is applied to the image before the |
| * transform attribute in the <code>Graphics2D</code> context is applied. |
| * The rendering attributes applied include the <code>Clip</code>, |
| * <code>Transform</code>, and <code>Composite</code> attributes. Note |
| * that no rendering is done if the specified transform is |
| * noninvertible. |
| * @param img the image to be rendered |
| * @param xform the transformation from image space into user space |
| * @see #transform |
| * @see #setTransform |
| * @see #setComposite |
| * @see #clip |
| * @see #setClip |
| */ |
| public void drawRenderedImage(RenderedImage img, AffineTransform xform) { |
| preparePainting(); |
| System.err.println("NYI: drawRenderedImage"); |
| } |
| |
| /** |
| * Renders a |
| * {@link RenderableImage}, |
| * applying a transform from image space into user space before drawing. |
| * The transformation from user space into device space is done with |
| * the current <code>Transform</code> in the <code>Graphics2D</code>. |
| * The specified transformation is applied to the image before the |
| * transform attribute in the <code>Graphics2D</code> context is applied. |
| * The rendering attributes applied include the <code>Clip</code>, |
| * <code>Transform</code>, and <code>Composite</code> attributes. Note |
| * that no rendering is done if the specified transform is |
| * noninvertible. |
| * <p> |
| * Rendering hints set on the <code>Graphics2D</code> object might |
| * be used in rendering the <code>RenderableImage</code>. |
| * If explicit control is required over specific hints recognized by a |
| * specific <code>RenderableImage</code>, or if knowledge of which hints |
| * are used is required, then a <code>RenderedImage</code> should be |
| * obtained directly from the <code>RenderableImage</code> |
| * and rendered using |
| * {@link #drawRenderedImage(RenderedImage, AffineTransform) drawRenderedImage}. |
| * @param img the image to be rendered |
| * @param xform the transformation from image space into user space |
| * @see #transform |
| * @see #setTransform |
| * @see #setComposite |
| * @see #clip |
| * @see #setClip |
| * @see #drawRenderedImage |
| */ |
| public void drawRenderableImage(RenderableImage img, |
| AffineTransform xform) { |
| preparePainting(); |
| System.err.println("NYI: drawRenderableImage"); |
| } |
| |
| /** |
| * Establishes the given color in the PostScript interpreter. |
| * @param c the color to set |
| * @throws IOException In case of an I/O problem |
| */ |
| public void establishColor(Color c) throws IOException { |
| gen.useColor(c); |
| } |
| |
| /** |
| * Renders the text specified by the specified <code>String</code>, |
| * using the current <code>Font</code> and <code>Paint</code> attributes |
| * in the <code>Graphics2D</code> context. |
| * The baseline of the first character is at position |
| * (<i>x</i>, <i>y</i>) in the User Space. |
| * The rendering attributes applied include the <code>Clip</code>, |
| * <code>Transform</code>, <code>Paint</code>, <code>Font</code> and |
| * <code>Composite</code> attributes. For characters in script systems |
| * such as Hebrew and Arabic, the glyphs can be rendered from right to |
| * left, in which case the coordinate supplied is the location of the |
| * leftmost character on the baseline. |
| * @param s the <code>String</code> to be rendered |
| * @param x the x-coordinate where the <code>String</code> |
| * should be rendered |
| * @param y the y-coordinate where the <code>String</code> |
| * should be rendered |
| * @see #setPaint |
| * @see java.awt.Graphics#setColor |
| * @see java.awt.Graphics#setFont |
| * @see #setTransform |
| * @see #setComposite |
| * @see #setClip |
| */ |
| public void drawString(String s, float x, float y) { |
| try { |
| if (customTextHandler != null && !textAsShapes) { |
| customTextHandler.drawString(s, x, y); |
| } else { |
| fallbackTextHandler.drawString(s, x, y); |
| } |
| } catch (IOException ioe) { |
| handleIOException(ioe); |
| } |
| } |
| |
| /** |
| * Fills the interior of a <code>Shape</code> using the settings of the |
| * <code>Graphics2D</code> context. The rendering attributes applied |
| * include the <code>Clip</code>, <code>Transform</code>, |
| * <code>Paint</code>, and <code>Composite</code>. |
| * @param s the <code>Shape</code> to be filled |
| * @see #setPaint |
| * @see java.awt.Graphics#setColor |
| * @see #transform |
| * @see #setTransform |
| * @see #setComposite |
| * @see #clip |
| * @see #setClip |
| */ |
| public void fill(Shape s) { |
| preparePainting(); |
| try { |
| gen.saveGraphicsState(); |
| |
| AffineTransform trans = getTransform(); |
| boolean newTransform = gen.getCurrentState().checkTransform(trans) |
| && !trans.isIdentity(); |
| |
| if (newTransform) { |
| gen.concatMatrix(trans); |
| } |
| Shape imclip = getClip(); |
| writeClip(imclip); |
| |
| establishColor(getColor()); |
| |
| applyPaint(getPaint(), true); |
| |
| gen.writeln("newpath"); |
| PathIterator iter = s.getPathIterator(IDENTITY_TRANSFORM); |
| processPathIterator(iter); |
| doDrawing(true, false, |
| iter.getWindingRule() == PathIterator.WIND_EVEN_ODD); |
| gen.restoreGraphicsState(); |
| } catch (IOException ioe) { |
| handleIOException(ioe); |
| } |
| } |
| |
| /** |
| * Commits a painting operation. |
| * @param fill filling |
| * @param stroke stroking |
| * @param nonzero true if the non-zero winding rule should be used when filling |
| * @exception IOException In case of an I/O problem |
| */ |
| protected void doDrawing(boolean fill, boolean stroke, boolean nonzero) |
| throws IOException { |
| preparePainting(); |
| if (fill) { |
| if (stroke) { |
| if (!nonzero) { |
| gen.writeln("gsave fill grestore stroke"); |
| } else { |
| gen.writeln("gsave eofill grestore stroke"); |
| } |
| } else { |
| if (!nonzero) { |
| gen.writeln("fill"); |
| } else { |
| gen.writeln("eofill"); |
| } |
| } |
| } else { |
| // if(stroke) |
| gen.writeln("stroke"); |
| } |
| } |
| |
| /** |
| * Returns the device configuration associated with this |
| * <code>Graphics2D</code>. |
| * @return the device configuration |
| */ |
| public GraphicsConfiguration getDeviceConfiguration() { |
| return GraphicsEnvironment.getLocalGraphicsEnvironment(). |
| getDefaultScreenDevice().getDefaultConfiguration(); |
| } |
| |
| /** |
| * Used to create proper font metrics |
| */ |
| private Graphics2D fmg; |
| |
| { |
| BufferedImage bi = new BufferedImage(1, 1, |
| BufferedImage.TYPE_INT_ARGB); |
| |
| fmg = bi.createGraphics(); |
| } |
| |
| /** |
| * Gets the font metrics for the specified font. |
| * @return the font metrics for the specified font. |
| * @param f the specified font |
| * @see java.awt.Graphics#getFont |
| * @see java.awt.FontMetrics |
| * @see java.awt.Graphics#getFontMetrics() |
| */ |
| public java.awt.FontMetrics getFontMetrics(java.awt.Font f) { |
| return fmg.getFontMetrics(f); |
| } |
| |
| /** |
| * Sets the paint mode of this graphics context to alternate between |
| * this graphics context's current color and the new specified color. |
| * This specifies that logical pixel operations are performed in the |
| * XOR mode, which alternates pixels between the current color and |
| * a specified XOR color. |
| * <p> |
| * When drawing operations are performed, pixels which are the |
| * current color are changed to the specified color, and vice versa. |
| * <p> |
| * Pixels that are of colors other than those two colors are changed |
| * in an unpredictable but reversible manner; if the same figure is |
| * drawn twice, then all pixels are restored to their original values. |
| * @param c1 the XOR alternation color |
| */ |
| public void setXORMode(Color c1) { |
| System.err.println("NYI: setXORMode"); |
| } |
| |
| |
| /** |
| * Copies an area of the component by a distance specified by |
| * <code>dx</code> and <code>dy</code>. From the point specified |
| * by <code>x</code> and <code>y</code>, this method |
| * copies downwards and to the right. To copy an area of the |
| * component to the left or upwards, specify a negative value for |
| * <code>dx</code> or <code>dy</code>. |
| * If a portion of the source rectangle lies outside the bounds |
| * of the component, or is obscured by another window or component, |
| * <code>copyArea</code> will be unable to copy the associated |
| * pixels. The area that is omitted can be refreshed by calling |
| * the component's <code>paint</code> method. |
| * @param x the <i>x</i> coordinate of the source rectangle. |
| * @param y the <i>y</i> coordinate of the source rectangle. |
| * @param width the width of the source rectangle. |
| * @param height the height of the source rectangle. |
| * @param dx the horizontal distance to copy the pixels. |
| * @param dy the vertical distance to copy the pixels. |
| */ |
| public void copyArea(int x, int y, int width, int height, int dx, |
| int dy) { |
| System.err.println("NYI: copyArea"); |
| } |
| |
| /* --- for debugging |
| public void transform(AffineTransform tx) { |
| System.out.println("transform(" + toArray(tx) + ")"); |
| super.transform(zx); |
| } |
| |
| public void scale(double sx, double sy) { |
| System.out.println("scale(" + sx + ", " + sy + ")"); |
| super.scale(sx, sy); |
| } |
| |
| public void translate(double tx, double ty) { |
| System.out.println("translate(double " + tx + ", " + ty + ")"); |
| super.translate(tx, ty); |
| } |
| |
| public void translate(int tx, int ty) { |
| System.out.println("translate(int " + tx + ", " + ty + ")"); |
| super.translate(tx, ty); |
| } |
| */ |
| |
| } |