Mega Code Archive

 
Categories / Java / SWT Jface Eclipse
 

Draw Graphics2D stuff on a swt composite

/*   * JFreeChart : a free chart library for the Java(tm) platform  *   *  * (C) Copyright 2000-2009, by Object Refinery Limited and Contributors.  *  * Project Info:  http://www.jfree.org/jfreechart/index.html  *  * This library is free software; you can redistribute it and/or modify it  * under the terms of the GNU Lesser General Public License as published by  * the Free Software Foundation; either version 2.1 of the License, or  * (at your option) any later version.  *  * This library is distributed in the hope that it will be useful, but  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public  * License for more details.  *  * You should have received a copy of the GNU Lesser General Public  * License along with this library; if not, write to the Free Software  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,  * USA.  *  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.  * in the United States and other countries.]  *  * ------------------  * SWTGraphics2D.java  * ------------------  * (C) Copyright 2006-2008, by Henry Proudhon and Contributors.  *  * Original Author:  Henry Proudhon (henry.proudhon AT ensmp.fr);  * Contributor(s):   Cedric Chabanois (cchabanois AT no-log.org);  *                   David Gilbert (for Object Refinery Limited);  *                   Ronnie Duan (see bug report 2583891);  *  * Changes  * -------  * 14-Jun-2006 : New class (HP);  * 29-Jan-2007 : Fixed the fillRect method (HP);  * 31-Jan-2007 : Moved the dummy JPanel to SWTUtils.java,  *               implemented the drawLine method (HP);  * 07-Apr-2007 : Dispose some of the swt ressources,  *               thanks to silent for pointing this out (HP);  * 23-May-2007 : Removed resource leaks by adding a resource pool (CC);  * 15-Jun-2007 : Fixed compile error for JDK 1.4 (DG);  * 22-Oct-2007 : Implemented clipping (HP);  * 22-Oct-2007 : Implemented some AlphaComposite support (HP);  * 23-Oct-2007 : Added mechanism for storing RenderingHints (which are  *               still ignored at this point) (DG);  * 23-Oct-2007 : Implemented drawPolygon(), drawPolyline(), drawOval(),  *               fillOval(), drawArc() and fillArc() (DG);  * 27-Nov-2007 : Implemented a couple of drawImage() methods (DG);  * 18-Nov-2008 : Check for GradientPaint in setPaint() method (DG);  * 27-Feb-2009 : Implemented fillPolygon() - see bug 2583891 (DG);  *  */ import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Composite; import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.Image; import java.awt.Paint; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; import java.awt.RenderingHints.Key; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.PathIterator; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; import java.awt.image.ImageObserver; import java.awt.image.RenderedImage; import java.awt.image.renderable.RenderableImage; import java.text.AttributedCharacterIterator; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.Path; import org.eclipse.swt.graphics.Resource; import org.eclipse.swt.graphics.Transform; /**  * This is a class utility to draw Graphics2D stuff on a swt composite.  * It is presently developed to use JFreeChart with the Standard  * Widget Toolkit but may be of a wider use later.  */ public class SWTGraphics2D extends Graphics2D {     /** The swt graphic composite */     private GC gc;     /**      * The rendering hints.  For now, these are not used, but at least the      * basic mechanism is present.      */     private RenderingHints hints;     /** A reference to the compositing rule to apply. This is necessary      * due to the poor compositing interface of the SWT toolkit. */     private java.awt.Composite composite;     /** A HashMap to store the Swt color resources. */     private Map colorsPool = new HashMap();     /** A HashMap to store the Swt font resources. */     private Map fontsPool = new HashMap();     /** A HashMap to store the Swt transform resources. */     private Map transformsPool = new HashMap();     /** A List to store the Swt resources. */     private List resourcePool = new ArrayList();     /**      * Creates a new instance.      *      * @param gc  the graphics context.      */     public SWTGraphics2D(GC gc) {         super();         this.gc = gc;         this.hints = new RenderingHints(null);         this.composite = AlphaComposite.getInstance(AlphaComposite.SRC, 1.0f);     }     /**      * Not implemented yet - see {@link Graphics#create()}.      *      * @return <code>null</code>.      */     public Graphics create() {         // TODO Auto-generated method stub         return null;     }     /**      * Not implemented yet - see {@link Graphics2D#getDeviceConfiguration()}.      *      * @return <code>null</code>.      */     public GraphicsConfiguration getDeviceConfiguration() {         // TODO Auto-generated method stub         return null;     }     /**      * Returns the current value for the specified hint key, or      * <code>null</code> if no value is set.      *      * @param hintKey  the hint key (<code>null</code> permitted).      *      * @return The hint value, or <code>null</code>.      *      * @see #setRenderingHint(RenderingHints.Key, Object)      */     public Object getRenderingHint(Key hintKey) {         return this.hints.get(hintKey);     }     /**      * Sets the value for a rendering hint.  For now, this graphics context      * ignores all hints.      *      * @param hintKey  the key (<code>null</code> not permitted).      * @param hintValue  the value (must be compatible with the specified key).      *      * @throws IllegalArgumentException if <code>hintValue</code> is not      *         compatible with the <code>hintKey</code>.      *      * @see #getRenderingHint(RenderingHints.Key)      */     public void setRenderingHint(Key hintKey, Object hintValue) {         this.hints.put(hintKey, hintValue);     }     /**      * Returns a copy of the hints collection for this graphics context.      *      * @return A copy of the hints collection.      */     public RenderingHints getRenderingHints() {         return (RenderingHints) this.hints.clone();     }     /**      * Adds the hints in the specified map to the graphics context, replacing      * any existing hints.  For now, this graphics context ignores all hints.      *      * @param hints  the hints (<code>null</code> not permitted).      *      * @see #setRenderingHints(Map)      */     public void addRenderingHints(Map hints) {         this.hints.putAll(hints);     }     /**      * Replaces the existing hints with those contained in the specified      * map.  Note that, for now, this graphics context ignores all hints.      *      * @param hints  the hints (<code>null</code> not permitted).      *      * @see #addRenderingHints(Map)      */     public void setRenderingHints(Map hints) {         if (hints == null) {             throw new NullPointerException("Null 'hints' argument.");         }         this.hints = new RenderingHints(hints);     }     /**      * Returns the current paint for this graphics context.      *      * @return The current paint.      *      * @see #setPaint(Paint)      */     public Paint getPaint() {         // TODO: it might be a good idea to keep a reference to the color         // specified in setPaint() or setColor(), rather than creating a         // new object every time getPaint() is called.         return SWTUtils.toAwtColor(this.gc.getForeground());     }     /**      * Sets the paint for this graphics context.  For now, this graphics      * context only supports instances of {@link Color} or      * {@link GradientPaint} (in the latter case there is no real gradient      * support, the paint used is the <code>Color</code> returned by      * <code>getColor1()</code>).      *      * @param paint  the paint (<code>null</code> not permitted).      *      * @see #getPaint()      * @see #setColor(Color)      */     public void setPaint(Paint paint) {         if (paint instanceof Color) {             setColor((Color) paint);         }         else if (paint instanceof GradientPaint) {             GradientPaint gp = (GradientPaint) paint;             setColor(gp.getColor1());         }         else {             throw new RuntimeException("Can only handle 'Color' at present.");         }     }     /**      * Returns the current color for this graphics context.      *      * @return The current color.      *      * @see #setColor(Color)      */     public Color getColor() {         // TODO: it might be a good idea to keep a reference to the color         // specified in setPaint() or setColor(), rather than creating a         // new object every time getPaint() is called.         return SWTUtils.toAwtColor(this.gc.getForeground());     }     /**      * Sets the current color for this graphics context.      *      * @param color  the color.      *      * @see #getColor()      */     public void setColor(Color color) {         org.eclipse.swt.graphics.Color swtColor = getSwtColorFromPool(color);         this.gc.setForeground(swtColor);         // handle transparency and compositing.         if (this.composite instanceof AlphaComposite) {             AlphaComposite acomp = (AlphaComposite) this.composite;             switch (acomp.getRule()) {             case AlphaComposite.SRC_OVER:                 this.gc.setAlpha((int) (color.getAlpha() * acomp.getAlpha()));                 break;             default:                 this.gc.setAlpha(color.getAlpha());                 break;             }         }     }     /**      * Sets the background colour.      *      * @param color  the colour.      */     public void setBackground(Color color) {         org.eclipse.swt.graphics.Color swtColor = getSwtColorFromPool(color);         this.gc.setBackground(swtColor);     }     /**      * Returns the background colour.      *      * @return The background colour.      */     public Color getBackground() {         return SWTUtils.toAwtColor(this.gc.getBackground());     }     /**      * Not implemented - see {@link Graphics#setPaintMode()}.      */     public void setPaintMode() {         // TODO Auto-generated method stub     }     /**      * Not implemented - see {@link Graphics#setXORMode(Color)}.      *      * @param color  the colour.      */     public void setXORMode(Color color) {         // TODO Auto-generated method stub     }     /**      * Returns the current composite.      *      * @return The current composite.      *      * @see #setComposite(Composite)      */     public Composite getComposite() {         return this.composite;     }     /**      * Sets the current composite.  This implementation currently supports      * only the {@link AlphaComposite} class.      *      * @param comp  the composite.      */     public void setComposite(Composite comp) {         this.composite = comp;         if (comp instanceof AlphaComposite) {             AlphaComposite acomp = (AlphaComposite) comp;             int alpha = (int) (acomp.getAlpha() * 0xFF);             this.gc.setAlpha(alpha);         }         else {             System.out.println("warning, can only handle alpha composite at the moment.");         }     }     /**      * Returns the current stroke for this graphics context.      *      * @return The current stroke.      *      * @see #setStroke(Stroke)      */     public Stroke getStroke() {         return new BasicStroke(this.gc.getLineWidth(), this.gc.getLineCap(),                 this.gc.getLineJoin());     }     /**      * Sets the stroke for this graphics context.  For now, this implementation      * only recognises the {@link BasicStroke} class.      *      * @param stroke  the stroke (<code>null</code> not permitted).      *      * @see #getStroke()      */     public void setStroke(Stroke stroke) {         if (stroke instanceof BasicStroke) {             BasicStroke bs = (BasicStroke) stroke;             // linewidth             this.gc.setLineWidth((int) bs.getLineWidth());             // line join             switch (bs.getLineJoin()) {                 case BasicStroke.JOIN_BEVEL :                     this.gc.setLineJoin(SWT.JOIN_BEVEL);                     break;                 case BasicStroke.JOIN_MITER :                     this.gc.setLineJoin(SWT.JOIN_MITER);                     break;                 case BasicStroke.JOIN_ROUND :                     this.gc.setLineJoin(SWT.JOIN_ROUND);                     break;             }             // line cap             switch (bs.getEndCap()) {                 case BasicStroke.CAP_BUTT :                     this.gc.setLineCap(SWT.CAP_FLAT);                     break;                 case BasicStroke.CAP_ROUND :                     this.gc.setLineCap(SWT.CAP_ROUND);                     break;                 case BasicStroke.CAP_SQUARE :                     this.gc.setLineCap(SWT.CAP_SQUARE);                     break;             }             // set the line style to solid by default             this.gc.setLineStyle(SWT.LINE_SOLID);             // apply dash style if any             float[] dashes = bs.getDashArray();             if (dashes != null) {                 int[] swtDashes = new int[dashes.length];                 for (int i = 0; i < swtDashes.length; i++) {                     swtDashes[i] = (int) dashes[i];                 }                 this.gc.setLineDash(swtDashes);             }         }         else {             throw new RuntimeException(                     "Can only handle 'Basic Stroke' at present.");         }     }     /**      * Applies the specified clip.      *      * @param s  the shape for the clip.      */     public void clip(Shape s) {         Path path = toSwtPath(s);         this.gc.setClipping(path);         path.dispose();     }     /**      * Returns the clip bounds.      *      * @return The clip bounds.      */     public Rectangle getClipBounds() {         org.eclipse.swt.graphics.Rectangle clip = this.gc.getClipping();         return new Rectangle(clip.x, clip.y, clip.width, clip.height);     }     /**      * Sets the clipping to the intersection of the current clip region and      * the specified rectangle.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the width.      * @param height  the height.      */     public void clipRect(int x, int y, int width, int height) {         org.eclipse.swt.graphics.Rectangle clip = this.gc.getClipping();         clip.intersects(x, y, width, height);         this.gc.setClipping(clip);     }     /**      * Returns the current clip.      *      * @return The current clip.      */     public Shape getClip() {         return SWTUtils.toAwtRectangle(this.gc.getClipping());     }     /**      * Sets the clip region.      *      * @param clip  the clip.      */     public void setClip(Shape clip) {         if (clip == null) {             return;         }         Path clipPath = toSwtPath(clip);         this.gc.setClipping(clipPath);         clipPath.dispose();     }     /**      * Sets the clip region to the specified rectangle.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the width.      * @param height  the height.      */     public void setClip(int x, int y, int width, int height) {         this.gc.setClipping(x, y, width, height);     }     /**      * Returns the current transform.      *      * @return The current transform.      */     public AffineTransform getTransform() {         Transform swtTransform = new Transform(this.gc.getDevice());         this.gc.getTransform(swtTransform);         AffineTransform awtTransform = toAwtTransform(swtTransform);         swtTransform.dispose();         return awtTransform;     }     /**      * Sets the current transform.      *      * @param t  the transform.      */     public void setTransform(AffineTransform t) {         Transform transform = getSwtTransformFromPool(t);         this.gc.setTransform(transform);     }     /**      * Concatenates the specified transform to the existing transform.      *      * @param t  the transform.      */     public void transform(AffineTransform t) {         Transform swtTransform = new Transform(this.gc.getDevice());         this.gc.getTransform(swtTransform);         swtTransform.multiply(getSwtTransformFromPool(t));         this.gc.setTransform(swtTransform);         swtTransform.dispose();     }     /**      * Applies a translation.      *      * @param x  the translation along the x-axis.      * @param y  the translation along the y-axis.      */     public void translate(int x, int y) {         Transform swtTransform = new Transform(this.gc.getDevice());         this.gc.getTransform(swtTransform);         swtTransform.translate(x, y);         this.gc.setTransform(swtTransform);         swtTransform.dispose();     }     /**      * Applies a translation.      *      * @param tx  the translation along the x-axis.      * @param ty  the translation along the y-axis.      */     public void translate(double tx, double ty) {         translate((int) tx, (int) ty);     }     /**      * Applies a rotation transform.      *      * @param theta  the angle of rotation.      */     public void rotate(double theta) {         Transform swtTransform = new Transform(this.gc.getDevice());         this.gc.getTransform(swtTransform);         swtTransform.rotate((float) (theta * 180 / Math.PI));         this.gc.setTransform(swtTransform);         swtTransform.dispose();     }     /**      * Not implemented - see {@link Graphics2D#rotate(double, double, double)}.      *      * @see java.awt.Graphics2D#rotate(double, double, double)      */     public void rotate(double theta, double x, double y) {         // TODO Auto-generated method stub     }     /**      * Applies a scale transform.      *      * @param scaleX  the scale factor along the x-axis.      * @param scaleY  the scale factor along the y-axis.      */     public void scale(double scaleX, double scaleY) {         Transform swtTransform = new Transform(this.gc.getDevice());         this.gc.getTransform(swtTransform);         swtTransform.scale((float) scaleX, (float) scaleY);         this.gc.setTransform(swtTransform);         swtTransform.dispose();     }     /**      * Applies a shear transform.      *      * @param shearX  the x-factor.      * @param shearY  the y-factor.      */     public void shear(double shearX, double shearY) {         Transform swtTransform = new Transform(this.gc.getDevice());         this.gc.getTransform(swtTransform);         Transform shear = new Transform(this.gc.getDevice(), 1f, (float) shearX,                 (float) shearY, 1f, 0, 0);         swtTransform.multiply(shear);         this.gc.setTransform(swtTransform);         swtTransform.dispose();     }     /**      * Draws the outline of the specified shape using the current stroke and      * paint settings.      *      * @param shape  the shape (<code>null</code> not permitted).      *      * @see #getPaint()      * @see #getStroke()      * @see #fill(Shape)      */     public void draw(Shape shape) {         Path path = toSwtPath(shape);         this.gc.drawPath(path);         path.dispose();     }     /**      * Draws a line from (x1, y1) to (x2, y2) using the current stroke      * and paint settings.      *      * @param x1  the x-coordinate for the starting point.      * @param y1  the y-coordinate for the starting point.      * @param x2  the x-coordinate for the ending point.      * @param y2  the y-coordinate for the ending point.      *      * @see #draw(Shape)      */     public void drawLine(int x1, int y1, int x2, int y2) {         this.gc.drawLine(x1, y1, x2, y2);     }     /**      * Draws the outline of the polygon specified by the given points, using      * the current paint and stroke settings.      *      * @param xPoints  the x-coordinates.      * @param yPoints  the y-coordinates.      * @param npoints  the number of points in the polygon.      *      * @see #draw(Shape)      */     public void drawPolygon(int [] xPoints, int [] yPoints, int npoints) {         drawPolyline(xPoints, yPoints, npoints);         if (npoints > 1) {             this.gc.drawLine(xPoints[npoints - 1], yPoints[npoints - 1],                     xPoints[0], yPoints[0]);         }     }     /**      * Draws a sequence of connected lines specified by the given points, using      * the current paint and stroke settings.      *      * @param xPoints  the x-coordinates.      * @param yPoints  the y-coordinates.      * @param npoints  the number of points in the polygon.      *      * @see #draw(Shape)      */     public void drawPolyline(int [] xPoints, int [] yPoints, int npoints) {         if (npoints > 1) {             int x0 = xPoints[0];             int y0 = yPoints[0];             int x1 = 0, y1 = 0;             for (int i = 1; i < npoints; i++) {                 x1 = xPoints[i];                 y1 = yPoints[i];                 this.gc.drawLine(x0, y0, x1, y1);                 x0 = x1;                 y0 = y1;             }         }     }     /**      * Draws an oval that fits within the specified rectangular region.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the frame width.      * @param height  the frame height.      *      * @see #fillOval(int, int, int, int)      * @see #draw(Shape)      */     public void drawOval(int x, int y, int width, int height) {         this.gc.drawOval(x, y, width - 1, height - 1);     }     /**      * Draws an arc that is part of an ellipse that fits within the specified      * framing rectangle.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the frame width.      * @param height  the frame height.      * @param arcStart  the arc starting point, in degrees.      * @param arcAngle  the extent of the arc.      *      * @see #fillArc(int, int, int, int, int, int)      */     public void drawArc(int x, int y, int width, int height, int arcStart,             int arcAngle) {         this.gc.drawArc(x, y, width - 1, height - 1, arcStart, arcAngle);     }     /**      * Draws a rectangle with rounded corners that fits within the specified      * framing rectangle.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the frame width.      * @param height  the frame height.      * @param arcWidth  the width of the arc defining the roundedness of the      *         rectangle's corners.      * @param arcHeight the height of the arc defining the roundedness of the      *         rectangle's corners.      *      * @see #fillRoundRect(int, int, int, int, int, int)      */     public void drawRoundRect(int x, int y, int width, int height,             int arcWidth, int arcHeight) {         this.gc.drawRoundRectangle(x, y, width - 1, height - 1, arcWidth,                 arcHeight);     }     /**      * Fills the specified shape using the current paint.      *      * @param shape  the shape (<code>null</code> not permitted).      *      * @see #getPaint()      * @see #draw(Shape)      */     public void fill(Shape shape) {         Path path = toSwtPath(shape);         // Note that for consistency with the AWT implementation, it is         // necessary to switch temporarily the foreground and background         // colours         switchColors();         this.gc.fillPath(path);         switchColors();         path.dispose();     }     /**      * Fill a rectangle area on the swt graphic composite.      * The <code>fillRectangle</code> method of the <code>GC</code>      * class uses the background color so we must switch colors.      * @see java.awt.Graphics#fillRect(int, int, int, int)      */     public void fillRect(int x, int y, int width, int height) {         this.switchColors();         this.gc.fillRectangle(x, y, width, height);         this.switchColors();     }     /**      * Fills the specified rectangle with the current background colour.      *      * @param x  the x-coordinate for the rectangle.      * @param y  the y-coordinate for the rectangle.      * @param width  the width.      * @param height  the height.      *      * @see #fillRect(int, int, int, int)      */     public void clearRect(int x, int y, int width, int height) {         Paint saved = getPaint();         setPaint(getBackground());         fillRect(x, y, width, height);         setPaint(saved);     }     /**      * Fills the specified polygon.      *      * @param xPoints  the x-coordinates.      * @param yPoints  the y-coordinates.      * @param npoints  the number of points.      */     public void fillPolygon(int[] xPoints, int[] yPoints, int npoints) {         int[] pointArray = new int[npoints * 2];         for (int i = 0; i < npoints; i++) {             pointArray[2 * i] = xPoints[i];             pointArray[2 * i + 1] = yPoints[i];         }         switchColors();         this.gc.fillPolygon(pointArray);         switchColors();     }     /**      * Draws a rectangle with rounded corners that fits within the specified      * framing rectangle.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the frame width.      * @param height  the frame height.      * @param arcWidth  the width of the arc defining the roundedness of the      *         rectangle's corners.      * @param arcHeight the height of the arc defining the roundedness of the      *         rectangle's corners.      *      * @see #drawRoundRect(int, int, int, int, int, int)      */     public void fillRoundRect(int x, int y, int width, int height,             int arcWidth, int arcHeight) {         switchColors();         this.gc.fillRoundRectangle(x, y, width - 1, height - 1, arcWidth,                 arcHeight);         switchColors();     }     /**      * Fills an oval that fits within the specified rectangular region.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the frame width.      * @param height  the frame height.      *      * @see #drawOval(int, int, int, int)      * @see #fill(Shape)      */     public void fillOval(int x, int y, int width, int height) {         switchColors();         this.gc.fillOval(x, y, width - 1, height - 1);         switchColors();     }     /**      * Fills an arc that is part of an ellipse that fits within the specified      * framing rectangle.      *      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the frame width.      * @param height  the frame height.      * @param arcStart  the arc starting point, in degrees.      * @param arcAngle  the extent of the arc.      *      * @see #drawArc(int, int, int, int, int, int)      */     public void fillArc(int x, int y, int width, int height, int arcStart,             int arcAngle) {         switchColors();         this.gc.fillArc(x, y, width - 1, height - 1, arcStart, arcAngle);         switchColors();     }     /**      * Returns the font in form of an awt font created      * with the parameters of the font of the swt graphic      * composite.      * @see java.awt.Graphics#getFont()      */     public Font getFont() {         // retrieve the swt font description in an os indept way         FontData[] fontData = this.gc.getFont().getFontData();         // create a new awt font with the appropiate data         return SWTUtils.toAwtFont(this.gc.getDevice(), fontData[0], true);     }     /**      * Set the font swt graphic composite from the specified      * awt font. Be careful that the newly created swt font      * must be disposed separately.      * @see java.awt.Graphics#setFont(java.awt.Font)      */     public void setFont(Font font) {         org.eclipse.swt.graphics.Font swtFont = getSwtFontFromPool(font);         this.gc.setFont(swtFont);     }     /**      * Returns the font metrics.      *      * @param font the font.      *      * @return The font metrics.      */     public FontMetrics getFontMetrics(Font font) {         return SWTUtils.DUMMY_PANEL.getFontMetrics(font);     }     /**      * Returns the font render context.      *      * @return The font render context.      */     public FontRenderContext getFontRenderContext() {         FontRenderContext fontRenderContext = new FontRenderContext(                 new AffineTransform(), true, true);         return fontRenderContext;     }     /**      * Not implemented - see {@link Graphics2D#drawGlyphVector(GlyphVector,      * float, float)}.      */     public void drawGlyphVector(GlyphVector g, float x, float y) {         // TODO Auto-generated method stub     }     /**      * Draws a string on the receiver. note that      * to be consistent with the awt method,      * the y has to be modified with the ascent of the font.      *      * @see java.awt.Graphics#drawString(java.lang.String, int, int)      */     public void drawString(String text, int x, int y) {         float fm = this.gc.getFontMetrics().getAscent();         this.gc.drawString(text, x, (int) (y - fm), true);     }     /**      * Draws a string at the specified position.      *      * @param text  the string.      * @param x  the x-coordinate.      * @param y  the y-coordinate.      */     public void drawString(String text, float x, float y) {         float fm = this.gc.getFontMetrics().getAscent();         this.gc.drawString(text, (int) x, (int) (y - fm), true);     }     /**      * Draws a string at the specified position.      *      * @param iterator  the string.      * @param x  the x-coordinate.      * @param y  the y-coordinate.      */     public void drawString(AttributedCharacterIterator iterator, int x, int y) {         // TODO Auto-generated method stub     }     /**      * Draws a string at the specified position.      *      * @param iterator  the string.      * @param x  the x-coordinate.      * @param y  the y-coordinate.      */     public void drawString(AttributedCharacterIterator iterator, float x,             float y) {         // TODO Auto-generated method stub     }     /**      * Not implemented - see {@link Graphics2D#hit(Rectangle, Shape, boolean)}.      *      * @return <code>false</code>.      */     public boolean hit(Rectangle rect, Shape text, boolean onStroke) {         // TODO Auto-generated method stub         return false;     }     /**      * Not implemented - see {@link Graphics#copyArea(int, int, int, int, int,      * int)}.      */     public void copyArea(int x, int y, int width, int height, int dx, int dy) {         // TODO Auto-generated method stub     }     /**      * Not implemented - see {@link Graphics2D#drawImage(Image,      * AffineTransform, ImageObserver)}.      *      * @param image  the image.      * @param xform  the transform.      * @param obs  an image observer.      *      * @return A boolean.      */     public boolean drawImage(Image image, AffineTransform xform,             ImageObserver obs) {         // TODO Auto-generated method stub         return false;     }     /**      * Draws an image.      *      * @param image  the image.      * @param op  the image operation.      * @param x  the x-coordinate.      * @param y  the y-coordinate.      */     public void drawImage(BufferedImage image, BufferedImageOp op, int x,             int y) {         org.eclipse.swt.graphics.Image im = new org.eclipse.swt.graphics.Image(                 this.gc.getDevice(), SWTUtils.convertToSWT(image));         this.gc.drawImage(im, x, y);         im.dispose();     }     /**      * Draws an SWT image with the top left corner of the image aligned to the      * point (x, y).      *      * @param image  the image.      * @param x  the x-coordinate.      * @param y  the y-coordinate.      */     public void drawImage(org.eclipse.swt.graphics.Image image, int x, int y) {         this.gc.drawImage(image, x, y);     }     /**      * Not implemented - see {@link Graphics2D#drawRenderedImage(RenderedImage,      * AffineTransform)}.      *      * @param image  the image.      * @param xform  the transform.      */     public void drawRenderedImage(RenderedImage image, AffineTransform xform) {         // TODO Auto-generated method stub     }     /**      * Not implemented - see {@link Graphics2D#drawRenderableImage(      * RenderableImage, AffineTransform)}.      *      * @param image  the image.      * @param xform  the transform.      */     public void drawRenderableImage(RenderableImage image,             AffineTransform xform) {         // TODO Auto-generated method stub     }     /**      * Draws an image with the top left corner aligned to the point (x, y).      *      * @param image  the image.      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param observer  ignored here.      *      * @return <code>true</code> if the image has been drawn.      */     public boolean drawImage(Image image, int x, int y,             ImageObserver observer) {         ImageData data = SWTUtils.convertAWTImageToSWT(image);         if (data == null) {             return false;         }         org.eclipse.swt.graphics.Image im = new org.eclipse.swt.graphics.Image(                 this.gc.getDevice(), data);         this.gc.drawImage(im, x, y);         im.dispose();         return true;     }     /**      * Draws an image with the top left corner aligned to the point (x, y),      * and scaled to the specified width and height.      *      * @param image  the image.      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the width for the rendered image.      * @param height  the height for the rendered image.      * @param observer  ignored here.      *      * @return <code>true</code> if the image has been drawn.      */     public boolean drawImage(Image image, int x, int y, int width, int height,             ImageObserver observer) {         ImageData data = SWTUtils.convertAWTImageToSWT(image);         if (data == null) {             return false;         }         org.eclipse.swt.graphics.Image im = new org.eclipse.swt.graphics.Image(                 this.gc.getDevice(), data);         org.eclipse.swt.graphics.Rectangle bounds = im.getBounds();         this.gc.drawImage(im, 0, 0, bounds.width, bounds.height, x, y, width,                 height);         im.dispose();         return true;     }     /**      * Draws an image.      *      * @param image (<code>null</code> not permitted).      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param bgcolor  the background color.      * @param observer  an image observer.      *      * @return A boolean.      */     public boolean drawImage(Image image, int x, int y, Color bgcolor,             ImageObserver observer) {         if (image == null) {             throw new IllegalArgumentException("Null 'image' argument.");         }         int w = image.getWidth(null);         int h = image.getHeight(null);         if (w == -1 || h == -1) {             return false;         }         Paint savedPaint = getPaint();         fill(new Rectangle2D.Double(x, y, w, h));         setPaint(savedPaint);         return drawImage(image, x, y, observer);     }     /**      * Draws an image.      *      * @param image  the image (<code>null</code> not permitted).      * @param x  the x-coordinate.      * @param y  the y-coordinate.      * @param width  the width.      * @param height  the height.      * @param bgcolor  the background colour.      * @param observer  an image observer.      *      * @return A boolean.      */     public boolean drawImage(Image image, int x, int y, int width, int height,             Color bgcolor, ImageObserver observer) {         if (image == null) {             throw new IllegalArgumentException("Null 'image' argument.");         }         int w = image.getWidth(null);         int h = image.getHeight(null);         if (w == -1 || h == -1) {             return false;         }         Paint savedPaint = getPaint();         fill(new Rectangle2D.Double(x, y, w, h));         setPaint(savedPaint);         return drawImage(image, x, y, width, height, observer);     }     /**      * Not implemented - see {@link Graphics#drawImage(Image, int, int, int,      *     int, int, int, int, int, ImageObserver)}.      *      * @param image  the image.      * @param dx1      * @param dy1      * @param dx2      * @param dy2      * @param sx1      * @param sy1      * @param sx2      * @param sy2      * @param observer      */     public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,             int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {         // TODO Auto-generated method stub         return false;     }     /**      * Not implemented - see {@link Graphics#drawImage(Image, int, int, int,      *     int, int, int, int, int, Color, ImageObserver)}.      *      * @param image  the image.      * @param dx1      * @param dy1      * @param dx2      * @param dy2      * @param sx1      * @param sy1      * @param sx2      * @param sy2      * @param bgcolor      * @param observer      */     public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,             int sx1, int sy1, int sx2, int sy2, Color bgcolor,             ImageObserver observer) {         // TODO Auto-generated method stub         return false;     }     /**      * Releases resources held by this instance (but note that the caller      * must dispose of the 'GC' passed to the constructor).      *      * @see java.awt.Graphics#dispose()      */     public void dispose() {         // we dispose resources we own but user must dispose gc         disposeResourcePool();     }     /**      * Add given swt resource to the resource pool. All resources added      * to the resource pool will be disposed when {@link #dispose()} is called.      *      * @param resource the resource to add to the pool.      * @return the swt <code>Resource</code> just added.      */     private Resource addToResourcePool(Resource resource) {         this.resourcePool.add(resource);         return resource;     }     /**      * Dispose the resource pool.      */     private void disposeResourcePool() {         for (Iterator it = this.resourcePool.iterator(); it.hasNext();) {             Resource resource = (Resource) it.next();             resource.dispose();         }         this.fontsPool.clear();         this.colorsPool.clear();         this.transformsPool.clear();         this.resourcePool.clear();     }     /**      * Internal method to convert a AWT font object into      * a SWT font resource. If a corresponding SWT font      * instance is already in the pool, it will be used      * instead of creating a new one. This is used in      * {@link #setFont()} for instance.      *      * @param font The AWT font to convert.      * @return The SWT font instance.      */     private org.eclipse.swt.graphics.Font getSwtFontFromPool(Font font) {         org.eclipse.swt.graphics.Font swtFont = (org.eclipse.swt.graphics.Font)         this.fontsPool.get(font);         if (swtFont == null) {             swtFont = new org.eclipse.swt.graphics.Font(this.gc.getDevice(),                     SWTUtils.toSwtFontData(this.gc.getDevice(), font, true));             addToResourcePool(swtFont);             this.fontsPool.put(font, swtFont);         }         return swtFont;     }     /**      * Internal method to convert a AWT color object into      * a SWT color resource. If a corresponding SWT color      * instance is already in the pool, it will be used      * instead of creating a new one. This is used in      * {@link #setColor()} for instance.      *      * @param awtColor The AWT color to convert.      * @return A SWT color instance.      */     private org.eclipse.swt.graphics.Color getSwtColorFromPool(Color awtColor) {         org.eclipse.swt.graphics.Color swtColor =                 (org.eclipse.swt.graphics.Color)                 // we can't use the following valueOf() method, because it                 // won't compile with JDK1.4                 // this.colorsPool.get(Integer.valueOf(awtColor.getRGB()));                 this.colorsPool.get(new Integer(awtColor.getRGB()));         if (swtColor == null) {             swtColor = SWTUtils.toSwtColor(this.gc.getDevice(), awtColor);             addToResourcePool(swtColor);             // see comment above             //this.colorsPool.put(Integer.valueOf(awtColor.getRGB()), swtColor);             this.colorsPool.put(new Integer(awtColor.getRGB()), swtColor);         }         return swtColor;     }     /**      * Internal method to convert a AWT transform object into      * a SWT transform resource. If a corresponding SWT transform      * instance is already in the pool, it will be used      * instead of creating a new one. This is used in      * {@link #setTransform()} for instance.      *      * @param awtTransform The AWT transform to convert.      * @return A SWT transform instance.      */     private Transform getSwtTransformFromPool(AffineTransform awtTransform) {         Transform t = (Transform) this.transformsPool.get(awtTransform);         if (t == null) {             t = new Transform(this.gc.getDevice());             double[] matrix = new double[6];             awtTransform.getMatrix(matrix);             t.setElements((float) matrix[0], (float) matrix[1],                     (float) matrix[2], (float) matrix[3],                     (float) matrix[4], (float) matrix[5]);             addToResourcePool(t);             this.transformsPool.put(awtTransform, t);         }         return t;     }     /**      * Perform a switch between foreground and background      * color of gc. This is needed for consistency with      * the awt behaviour, and is required notably for the      * filling methods.      */     private void switchColors() {         org.eclipse.swt.graphics.Color bg = this.gc.getBackground();         org.eclipse.swt.graphics.Color fg = this.gc.getForeground();         this.gc.setBackground(fg);         this.gc.setForeground(bg);     }     /**      * Converts an AWT <code>Shape</code> into a SWT <code>Path</code>.      *      * @param shape  the shape (<code>null</code> not permitted).      *      * @return The path.      */     private Path toSwtPath(Shape shape) {         int type;         float[] coords = new float[6];         Path path = new Path(this.gc.getDevice());         PathIterator pit = shape.getPathIterator(null);         while (!pit.isDone()) {             type = pit.currentSegment(coords);             switch (type) {                 case (PathIterator.SEG_MOVETO):                     path.moveTo(coords[0], coords[1]);                     break;                 case (PathIterator.SEG_LINETO):                     path.lineTo(coords[0], coords[1]);                     break;                 case (PathIterator.SEG_QUADTO):                     path.quadTo(coords[0], coords[1], coords[2], coords[3]);                     break;                 case (PathIterator.SEG_CUBICTO):                     path.cubicTo(coords[0], coords[1], coords[2],                             coords[3], coords[4], coords[5]);                     break;                 case (PathIterator.SEG_CLOSE):                     path.close();                     break;                 default:                     break;             }             pit.next();         }         return path;     }     /**      * Converts an SWT transform into the equivalent AWT transform.      *      * @param swtTransform  the SWT transform.      *      * @return The AWT transform.      */     private AffineTransform toAwtTransform(Transform swtTransform) {         float[] elements = new float[6];         swtTransform.getElements(elements);         AffineTransform awtTransform = new AffineTransform(elements);         return awtTransform;     } }