|  | <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> | 
|  | <html> | 
|  | <head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
|  | <meta name="GENERATOR" content="Mozilla/4.74 [en] (Windows NT 5.0; U) [Netscape]"> | 
|  | <meta name="ProgId" content="FrontPage.Editor.Document"> | 
|  | <title>Introduction to SWT Graphics</title> | 
|  | <link | 
|  | href="../default_style.css" | 
|  | rel=stylesheet> | 
|  | </head> | 
|  | <body link="#0000FF" vlink="#800080"> | 
|  | <div align="right"><font size="-2">Copyright © 2003 International Business Machines | 
|  | Corp.</font> | 
|  | <table border=0 cellspacing=0 cellpadding=2 width="100%"> | 
|  | <tr> | 
|  | <td align=LEFT valign=TOP colspan="2" bgcolor="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF"> Eclipse | 
|  | Corner Article</font></b></td> | 
|  | </tr> | 
|  | </table> | 
|  | </div> | 
|  | <h1> <img src="images/Idea.jpg" height=86 width=120 align=CENTER></h1> | 
|  | <center> | 
|  | <h1> Graphics Context - Quick on the draw</h1> | 
|  | </center> | 
|  | <blockquote><b>Summary</b> <br> | 
|  | The package <code>org.eclipse.swt.graphics</code> contains classes that allows | 
|  | management of graphics resources. Graphics can be drawn on anything that implements | 
|  | <code>org.eclipse.swt.graphics.Drawable, </code>which includes <code>org.eclipse.swt.widgets.Control</code> | 
|  | and <code>org.eclipse.swt.graphics.Image</code>. The class <code>org.eclipse.swt.graphics.GC | 
|  | </code>encapsulates all of the drawing API, including how to draw lines and | 
|  | shapes, draw text and images and fill shapes. This article shows how to | 
|  | use a GC to draw onto an Image, or onto a control through its paintEvent callback. | 
|  | The Canvas control, specifically designed for drawing operations, has a number | 
|  | of constructor style bits that allow you to determine when and how painting | 
|  | occurs, and the article shows how to use these. | 
|  | <p><b>By Joe Winchester, IBM</b> <br> | 
|  | July 3, 2003</blockquote> | 
|  | <hr width="100%"> | 
|  | <br> | 
|  | Table of contents: | 
|  | <ul> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Graphics Context">Graphics | 
|  | Context</a></li> | 
|  | <ul> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Graphics Context">Drawing | 
|  | on an Image</a></li> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Graphics Context">Drawing | 
|  | on a Control</a></li> | 
|  | </ul> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Clipping">Clipping</a></li> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Canvas">Canvas</a></li> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Drawing lines and">Drawing | 
|  | lines and shapes</a></li> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Drawing Text">Drawing | 
|  | text</a></li> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Filling shapes">Filling | 
|  | shapes</a></li> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#XOR">XOR</a></li> | 
|  | <li> <a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Drawing Images">Drawing | 
|  | images</a></li> | 
|  | </ul> | 
|  | The SWT graphics system uses the same coordinate convention used for controls, | 
|  | where the origin is at 0,0 is the top left corner, and the x axis increases to | 
|  | the right while the y axis increases downwards.  The Point class is used | 
|  | to represent both a location (a position in the coordinate system) and also an | 
|  | offset (there is no Dimension class in SWT - the size of a rectangle is represented | 
|  | by a Point capturing the x and y offset from its origin). | 
|  | <h1> <a NAME="Graphics Context"></a>Graphics Context</h1> | 
|  | Graphics can be drawn on anything that implements <code>org.eclipse.swt.graphics.Drawable</code>.  | 
|  | This includes a Control, an Image, a Display device or a Printer device.  | 
|  | The class <code>org.eclipse.swt.graphics.GC</code> is a graphics context that encapsulates | 
|  | the drawing operations that can be performed.  There are two common ways | 
|  | to use a GC; either by creating one using the Drawable instance as a constructor | 
|  | argument, or else using a GC that's given to you as part of a paintEvent callback. | 
|  | <h2> Drawing on an Image</h2> | 
|  | The code below creates a GC with an image as its argument and draws two lines | 
|  | on it, <img src="images/tag_1.gif" height=13 width=24> one from the top left (0,0) | 
|  | to the bottom right, and <img src="images/tag_2.gif" height=13 width=24> one from | 
|  | the top right to the bottom left. | 
|  | <p><code>    Image image = new Image(display,"C:/devEclipse_02/eclipse/plugins/org.eclipse.platform_2.0.2/eclipse_lg.gif");</code> | 
|  | <br> | 
|  | <code>    GC gc = new GC(image);</code> <br> | 
|  | <code>    Rectangle bounds = image.getBounds();</code> <br> | 
|  | <img src="images/tag_1.gif" height=13 width=24><code> gc.drawLine(0,0,bounds.width,bounds.height);</code> | 
|  | <br> | 
|  | <img src="images/tag_2.gif" height=13 width=24><code> gc.drawLine(0,bounds.height,bounds.width,0);</code> | 
|  | <br> | 
|  | <img src="images/tag_3.gif" height=13 width=24><code> gc.dispose();</code> <br> | 
|  | <code>    image.dispose();</code> <br> | 
|  |   | 
|  | <table BORDER > | 
|  | <caption> | 
|  | <TBODY> | 
|  | <br></TBODY> | 
|  | </caption> | 
|  | <tr> | 
|  | <td> <i>Original image </i></td> | 
|  | <td><i>Image after the GC draws across it</i></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td><img src="images/image_lg_orig.gif" height=164 width=115></td> | 
|  | <td><img src="images/image_lg_lines.gif" height=164 width=115></td> | 
|  | </tr> | 
|  | </table> | 
|  | <p>When creating a GC you must be responsible for disposing it <img src="images/tag_3.gif" height=13 width=24> | 
|  | by calling its dispose() method. For more information on how to manage SWT resources | 
|  | see <a href="http://www.eclipse.org/articles/swt-design-2/swt-design-2.html">SWT: | 
|  | The Standard Widget Toolkit.</a>  A GC that's instantiated by the program | 
|  | should be drawn upon and then disposed as soon as possible.  This is because | 
|  | each GC requires an underlying platform resource, and on some operating systems | 
|  | these may be scarce, such as Windows 98 that only allows 5 GC objects to be | 
|  | created before it runs out resources. | 
|  | <h2> Drawing on a Control</h2> | 
|  | The class <code>org.eclipse.swt.widgets.Control</code> is a Drawable, so you could | 
|  | draw onto a Control the same way you draw onto an Image (passing the Control as | 
|  | the argument of GC to draw onto it), however unlike drawing on an image (that | 
|  | permanently changes the data making up the graphic), if you use a GC to draw onto | 
|  | a control you must be aware that when the operating system itself draws the control | 
|  | it will overwrite your changes.  The correct way to draw onto a control is | 
|  | by adding a listener to its paint event.  The listener class is <code>org.eclipse.swt.events.PaintListener</code>, | 
|  | and the callback method argument is an instance of <code>org.eclipse.swt.events.PaintEvent</code>.  | 
|  | The PaintEvent includes a GC that you can send message to, that is already prepared | 
|  | to draw onto the control and includes the damaged area. | 
|  | <p>The following code <img src="images/tag_1.gif" height=13 width=24> adds a paint | 
|  | listener to a Shell, and in the paintControl callback method <img src="images/tag_2.gif" height=13 width=24> | 
|  | draws a line from the origin to bottom right corner. | 
|  | <p><code>    Shell shell = new Shell(display);</code> <br> | 
|  | <img src="images/tag_1.gif" height=13 width=24><code> shell.addPaintListener(new PaintListener(){</code> | 
|  | <br> | 
|  | <code>        public void paintControl(PaintEvent | 
|  | e){</code> <br> | 
|  | <code>            Rectangle | 
|  | clientArea = shell.getClientArea();</code> <br> | 
|  | <img src="images/tag_2.gif" height=13 width=24><code>         | 
|  | e.gc.drawLine(0,0,clientArea.width,clientArea.height);</code> <br> | 
|  | <code>        }</code> <br> | 
|  | <code>    });</code> <br> | 
|  | <code>    shell.setSize(150,150)</code> | 
|  | <p><img src="images/ShellDrawnLine.gif" height=215 width=267> | 
|  | <p>Although the size of the Shell is set to (150,150), the area that can be drawn | 
|  | onto is smaller.  This is known as the client area, and takes into account | 
|  | any trim or borders; for a Shell this includes its edges, titlebar and menubar.  | 
|  | To determine the clientArea of any Composite use the method <code>getClientArea().</code> | 
|  | <p>The application always get a paint event after the underlying OS has drawn | 
|  | the control, so any drawing done to the paint event's GC will be shown on top | 
|  | of the control.  There are some exceptions to this, such as for a ToolBar | 
|  | where on certain platforms the items are heavyweight controls that can't be | 
|  | drawn on top of, however this is not considered normal behavior.  For general-purpose | 
|  | drawing the control <code><a href="http://eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html#Canvas">org.eclipse.swt.widgets.Canvas</a></code> | 
|  | can be used that is optimized for graphics operations. | 
|  | <h1> <a NAME="Clipping"></a>Clipping</h1> | 
|  | The clipping area of a GC is the portion onto which visible drawing occurs. By | 
|  | default a GC is clipped to the bounds of the drawable that it was constructed | 
|  | with. Altering the clipping area of a GC allows you to create graphic effects.  | 
|  | An example of this is if you wanted to fill a triangle shape that had a portion | 
|  | of its edges missing.  One way to do this would be to draw multiple polygons | 
|  | rectangles making up the shape, another way however is to fill the shape, but | 
|  | to clip the GC so that the edges are outside the clipping area. | 
|  | <p><code>    shell.addPaintListener(new PaintListener() {</code> <br> | 
|  | <code>        public void paintControl(PaintEvent | 
|  | e) {</code> <br> | 
|  | <code>            Rectangle | 
|  | clientArea = shell.getClientArea();</code> <br> | 
|  | <code>            int width | 
|  | = clientArea.width;</code> <br> | 
|  | <code>            int height | 
|  | = clientArea.height;</code> <br> | 
|  | <img src="images/tag_2.gif" height=13 width=24><code>         | 
|  | e.gc.setClipping(20,20,width - 40, height - 40);</code> <br> | 
|  | <code>            e.gc.setBackground(display.getSystemColor(SWT.COLOR_CYAN));</code> | 
|  | <br> | 
|  | <img src="images/tag_1.gif" height=13 width=24><code>         | 
|  | e.gc.fillPolygon(new int[] {0,0,width,0,width/2,height});</code> <br> | 
|  | <code>        }</code> <br> | 
|  | <code>    });</code> | 
|  | <p>This code draws a triangle on a Shell as a polygon from  the <img src="images/tag_1.gif" height=13 width=24> | 
|  | top left, top right, and center of the bottom edge. Beforehand however, the | 
|  | GC is clipped with a rectangle <img src="images/tag_2.gif" height=13 width=24> | 
|  | that reduces the client area with a margin of 20 pixels wide, so only the clipped | 
|  | rectangle is draw. | 
|  | <p><img src="images/ClippedTriangles.gif" height=191 width=562> | 
|  | <p>When a paintEvent occurs for a control the GC is always clipped to just the | 
|  | area that needs repainting. For example, if another window is moved in front | 
|  | of an SWT shell and then moved away, the newly revealed portion of the GUI is | 
|  | marked as damaged and a paint event is queued.  When the paint event occurs, | 
|  | the <code>paintControl(PaintEvent evt)</code> method argument contains the area | 
|  | of the Control that requires redrawing in its x, y, width and height fields.  | 
|  | The damage to the control can be complex containing multiple disjoint rectangles, | 
|  | and if there is more than one damaged area of a control when the paint event | 
|  | occurs the damaged areas are merged into a single rectangle representing the | 
|  | union of the damaged areas. This step is performed by the underlying platform | 
|  | and is designed to aid performance as multiple paint events are processed in | 
|  | a single callback. | 
|  | <p>In the example above that fills a clipped triangle  each time the <code>paintControl(PaintEvent)</code> | 
|  | method is called, an optimization could be to look at the PaintEvent's area.  | 
|  | It maybe that the paint event doesn't even intersect the shape being drawn in | 
|  | which case no drawing need occur, or if only a portion of the drawing is needs | 
|  | repainting then only this is drawn.  Depending on the type of drawing, | 
|  | working out which portion of a GC to selectively redraw however can be more | 
|  | expensive than just relying on the fact the GC is clipped, and in practice code | 
|  | inside paint events often just ignores the damaged area and re-does all of the | 
|  | GC drawing, relying on clipping to ensure only the damaged area is refreshed. | 
|  | <p>If a program needs to manually damage an area of a control this can be done | 
|  | using <code>Control.redraw(int x, int y, int width, int height)</code>, or <code>Control.redraw()</code> | 
|  | to damage the entire client area.  The area is marked as damaged and will | 
|  | be included in the next paint event that occurs.  To cause a synchronous | 
|  | and immediate paint event to occur use the method <code>Control.update()</code> | 
|  | that will force all outstanding paint requests to be processed for the control. | 
|  | If there are no paint request  (i.e. none of the client area is damaged), | 
|  | then <code>update()</code> will do nothing. | 
|  | <h1> <a NAME="Canvas"></a>Canvas</h1> | 
|  | Although any Control can be drawn onto through its paintEvent, the subclass org.eclipse.swt.widgets.<code>Canvas</code> | 
|  | is specifically designed for graphics operations. This can be done either by using | 
|  | a Canvas and adding a paint listener, or through subclassing to create a re-usable | 
|  | Custom Control.  Canvas has a number of style bits that can be used to affect | 
|  | how painting occurs. | 
|  | <p>The default behavior for a Canvas is that before it paints itself the entire | 
|  | client area is filled with the current background color.  This can create | 
|  | screen flicker, because if the paintEvent also draws onto the GC, then the user | 
|  | sees a flash between the original background being filled, and the drawing occurring.  | 
|  | One way to avoid this is to use the style bit SWT.NO_BACKGROUND when creating | 
|  | the Canvas.  This prevents the native background from being drawn, however | 
|  | it means the program must be responsible for drawing every pixel of the client | 
|  | area. | 
|  | <p>When a widget is resized a paint event occurs.  This can create screen | 
|  | flicker as repeated repainting of the client area occurs.  Flicker is also | 
|  | known as flash, and the style bit SWT.NO_REDRAW_RESIZE can be used to reduce | 
|  | this.  When NO_REDRAW_RESIZE is used and the control's size is reduced | 
|  | no paint event is generated.  This means there will be no flash as the | 
|  | control is not unnecessarily redrawn, and if the size is increased then the | 
|  | paint event's GC is clipped set to just the area that needs repainting.  | 
|  | This is the newly revealed bottom and right edge rectangles in a shape like | 
|  | a backwards L. | 
|  | <p>The style bit NO-REDRAW_RESIZE works well to reduce flicker if a fixed-size | 
|  | drawing is being done on the GC, and each newly exposed area generates a paint | 
|  | event onto which a fresh piece of the drawing occurs.  Incorrectly used | 
|  | however, NO_REDRAW_RESIZE can lead to a graphic effect known as cheese.  | 
|  | Cheese is a general term that applies when a portion of a widget is not updated | 
|  | correctly following a resize. An example of  is shown below where the paint | 
|  | event needs to update the entire client area, such as <img src="images/tag_1.gif" height=13 width=24> | 
|  | fill it with an oval shape.  Because no paint event occurs when the window | 
|  | is reduced in size the shape is not redrawn when the size is decreased, and | 
|  | when the window is made larger because the GC is clipped to just the damaged | 
|  | area Cheese occurs in the newly expanded area because the previous drawing is | 
|  | not erased ( as the paint event is clipped to only the newly exposed area ). | 
|  | <p><code>    shell.setLayout(new FillLayout());</code> <br> | 
|  | <img src="images/tag_2.gif" height=13 width=24><code> final Canvas canvas = new Canvas(shell,SWT.NO_REDRAW_RESIZE);</code> | 
|  | <p><code>    canvas.addPaintListener(new PaintListener() {</code> <br> | 
|  | <code>        public void paintControl(PaintEvent | 
|  | e) {</code> <br> | 
|  | <code>            Rectangle | 
|  | clientArea = canvas.getClientArea();</code> <br> | 
|  | <code>            e.gc.setBackground(display.getSystemColor(SWT.COLOR_CYAN));</code> | 
|  | <br> | 
|  | <img src="images/tag_1.gif" height=13 width=24><code>         | 
|  | e.gc.fillOval(0,0,clientArea.width,clientArea.height);</code> <br> | 
|  | <code>        }</code> <br> | 
|  | <code>    });</code> | 
|  | <p>When the canvas size is increased the GC is clipped to just the area that needs | 
|  | repainting and cheese occurs. | 
|  | <p><img src="images/Cheese_Complete.gif"> | 
|  | <p>To correct this problem in line <img src="images/tag_2.gif" height=13 width=24> | 
|  | the style bit of SWT.NONE should be used so that the GC is not clipped on expansion, | 
|  | and a paint event occurs even when the shell size is reduced so the full oval | 
|  | can be repainted. | 
|  | <p><img src="images/tag_2.gif" height=13 width=24><code> final Canvas canvas = new Canvas(shell,SWT.NONE);</code> | 
|  | <p>For any SWT widget, if more than one rectangle is damaged then the platform | 
|  | merges these into a single damaged area that is the union of all damaged rectangles | 
|  | so the SWT program only processes a single paint event. The style bit NO_MERGE_PAINTS | 
|  | on Canvas can be used to override this behavior which means the listener will | 
|  | be called with a single paint event for every separate damaged rectangle. | 
|  | <p>The style bits NO_BACKGROUND, NO_REDRAW_RESIZE and NO_MERGE_PAINTS can be used | 
|  | with any Composite or subclass, including Canvas, Shell, or Group.  Although | 
|  | this is allowed by SWT ( no exceptions will be thrown ) the Composite class's | 
|  | Javadoc includes the following style bit warning <i>"... their behavior is undefined | 
|  | if they are used with subclasses of <code>Composite</code> other than <code>Canvas</code>".  | 
|  | </i>The Canvas class is therefore the preferred control to use when performing | 
|  | arbitrary drawing operations. | 
|  | <p>Another way to reduce flicker is to batch up the drawing that occurs on the | 
|  | display by double buffering.  Double buffering is a technique where the | 
|  | drawing occurs onto a GC that is not the one used on the paintEvent, and the | 
|  | contents are then copied across. To do this you can create an Image with the | 
|  | same size as the Canvas' client area and then draw onto this with a <code>GC(Image)</code>;  | 
|  | The final image is then transferred across to the paint event's GC with a single | 
|  | <code>drawImage(Image image, int x, int y) </code>method call.  When using | 
|  | this technique be aware that some platforms perform native double buffering | 
|  | for you already, so you may in fact be triple buffering. | 
|  | <h1> <a NAME="Drawing lines and"></a>Drawing lines and shapes</h1> | 
|  | A GC has a number of methods that allow lines to be drawn on it, either between | 
|  | two points, a series of interconnected points, or a pre-defined shape.  Lines | 
|  | are drawn in the foreground color of the GC and can be drawn in a number of styles | 
|  | and with different thickeness.  For a paint event the GC has the same attributes | 
|  | as the control that fired the event (foreground / background color and font), | 
|  | and the default line style is solid with a width of 1 pixel. | 
|  | <h2> <code>GC.drawLine(int x1, int y1, int x2, int y2);</code></h2> | 
|  | Draw a line between two points on the drawable surface beginning at x1,y1 and | 
|  | ending at x2,y2.  The end points are included in the line, and if they are | 
|  | the same then a single pixel dot will be drawn. | 
|  | <h2> <code>GC.drawPolyline(int[] pointArray);</code></h2> | 
|  | Draw a series of interconnecting lines with the int[] representing x and y positions | 
|  | for consecutive points.  The statement: <br> | 
|  | <code>gc.drawPolyline(new int[] { 25,5,45,45,5,45 });</code> <br> | 
|  | draws a line from 25,5 to 45,45 and then from 45,45 onto 5,45. | 
|  | <p><img src="images/PolygonClient.gif" height=94 width=161> | 
|  | <h2> <code>GC.drawPolygon(int[] pointArray);</code></h2> | 
|  | Similar to <code>drawPolyline(int[])</code> except that the last point is joined to | 
|  | the first <br> | 
|  | <code>gc.drawPolygon(new int[] { 25,5,45,45,5,45 });</code> <br> | 
|  | This draws the three corners of the triangle and, by joining the point at 5,45 | 
|  | with 25,5 completes the shape by creating a contained area <br> | 
|  | <img src="images/PolygonClient.gif" height=94 width=161> | 
|  | <h2> <code>GC.drawRectangle(int x, int y, int width, int height);</code></h2> | 
|  | Draw a rectangle with the top left corner at x,y with the specified with and height | 
|  | <br> | 
|  | <code>gc.drawRectangle(5,5,90,45);</code> <br> | 
|  | draws a rectangle with one corner at 5,5 and the opposite corner at 95,50; <br> | 
|  | <img src="images/RectangleClient.gif" height=97 width=174> | 
|  | <p>When a rectangle is drawn the bottom and right edges are drawn and it is conceptually | 
|  | similar to lines being drawn between its four corners.  As well as passing | 
|  | the x,y,width and height as individual arguments the method is overloaded so | 
|  | you can pass in the entire Rectangle - <code>GC.drawRectangle(Rectangle);</code> | 
|  | <h2> <code>GC.drawRoundedRectangle(int x, int y, int width, int height, int arcWidth, | 
|  | int arcHeight);</code></h2> | 
|  | A rounded rectangle differs from a standard rectangle in that its corners are | 
|  | rounded.  The rounding on each corner can be thought of as 1/4 of an oval, | 
|  | and the arcWidth and arcHeight specify the width and height of the full oval. | 
|  | <br> | 
|  | <code>gc.drawRoundedRectangle(5,5,90,45,25,15); </code>draws a rounded rectangle with | 
|  | a top left corner of 5,5.  The figure below shows a zoomed picture of the | 
|  | bottom right corner together with an imaginary oval shown with a width of 25 and | 
|  | a height of 15 to show how the rounded corner is created from 1/4 of the oval. | 
|  | <p><img src="images/RoundedRectangleClient.gif" height=121 width=449> | 
|  | <p>The implementation of the rounded rectangle could be achieved with 4 calls | 
|  | to <code>drawArc() </code>and 4 to <code>drawLine(). </code>However on some platforms | 
|  | such as Windows or Photon there is an optimized platform API that SWT uses. | 
|  | <h2> <code>GC.drawOval(int x, int y, int width, int height);</code></h2> | 
|  | An oval is draw within the rectangle defined by its top left corner (x,y) and | 
|  | its width and height.  To draw a circle set the width and height to be the | 
|  | same value. <br> | 
|  | <code>gc.drawOval(5,5,90,45);</code> | 
|  | <p><img src="images/OvalClient.gif" height=95 width=188> | 
|  | <h2> <code>GC.drawArc(int x, int y, int width, int height, int startAngle, int endAngle);</code></h2> | 
|  | An arc is drawn within the area bounded by the rectangle whose top left corner | 
|  | is x,y and has the specified width and height.  The startAngle is on the | 
|  | horizontal x axis, so 0 degrees does not represent North but instead can be thought | 
|  | of as pointing East.  The arc is drawn anticlockwise for the number of degrees | 
|  | specified by the endAngle <br> | 
|  | <code>gc.drawArc(5,5,90,45,90,200);</code> <br> | 
|  | This draws an arc beginning at 90 degrees, which is vertical ( 0 degrees being | 
|  | horizontal ), and the arc continues for 200 degrees.  The arc does not stop | 
|  | when it reaches the endAngle of 200 degrees relative to the 0 axis, rather it | 
|  | stops when it has traversed 200 degrees relative to its starting position. | 
|  | <p><img src="images/ArcClient.gif" height=87 width=161> | 
|  | <h2> <code>GC.setLineStyle(int style);</code></h2> | 
|  | Lines can be drawn in a number of styles that are defined as static constants | 
|  | on the class <code>org.eclipse.swt.SWT </code>beginning LINE_. <br> | 
|  |   | 
|  | <table BORDER > | 
|  | <caption> | 
|  | <TBODY> | 
|  | <br></TBODY> | 
|  | </caption> | 
|  | <tr> | 
|  | <td>SWT.LINE_SOLID</td> | 
|  | <td><img src="images/Line_SOLID.gif" height=16 width=292></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td>SWT.LINE_DOT</td> | 
|  | <td><img src="images/LINE_DOT.gif" height=16 width=292></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td>SWT.LINE_DASH</td> | 
|  | <td><img src="images/LINE_DASH.gif" height=16 width=292></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td>SWT.LINE_DASHDOT</td> | 
|  | <td><img src="images/LINE_DASHDOT.gif" height=16 width=292></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td>SWT.LINE_DASHDOTDOT</td> | 
|  | <td><img src="images/LINE_DASHDOTDOT.gif" height=16 width=292></td> | 
|  | </tr> | 
|  | </table> | 
|  | <h2> <code>GC.setLineWidth(int width);</code></h2> | 
|  | The default width for a line is 1 pixel, however this can be changed by setting | 
|  | the lineWidth of the GC. <br> | 
|  |   | 
|  | <table BORDER > | 
|  | <caption> | 
|  | <TBODY> | 
|  | <br></TBODY> | 
|  | </caption> | 
|  | <tr> | 
|  | <td>gc.setLineWidth(2);</td> | 
|  | <td><img src="images/Width_2.gif" height=16 width=292></td> | 
|  | </tr> | 
|  | <tr> | 
|  | <td>gc.setLineWidth(4);</td> | 
|  | <td><img src="images/Width_4.gif" height=16 width=292></td> | 
|  | </tr> | 
|  | </table> | 
|  | <p>Because line styles and width affect all of the draw operations, allowing you | 
|  | to achieve effects such as a dotted rectangle or an oval with a thick line. | 
|  | <p><code>gc.setLineWidth(3);</code> <br> | 
|  | <code>gc.drawOval(5,5,40,40);</code> <br> | 
|  | <code>gc.setLineWidth(1);</code> <br> | 
|  | <code>gc.setLineStyle(SWT.LINE_DOT);</code> <br> | 
|  | <code>gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));</code> <br> | 
|  | <code>gc.drawRectangle(60,5,60,40);</code> | 
|  | <p><img src="images/LineShapes.gif" height=91 width=172> <br> | 
|  | When a property such as a line width, line style or color is changed on a GC | 
|  | this affects all subsequent drawing operations.  The code snippet above | 
|  | changes the width to 3 to draw the oval, but it then changes it back to 1 before | 
|  | drawing the dotted blue rectangle.  Forgetting to revert values in a GC | 
|  | after modifying them is a common bug when doing SWT graphics programming. | 
|  | <h1> <a NAME="Drawing Text"></a>Drawing text</h1> | 
|  | Text can be drawn onto a GC, the glyphs are drawn in the GC's foreground color | 
|  | and font, and the area it occupies is drawn with the GC's background color.  | 
|  | To draw text you define its top left corner, width and height.  There are | 
|  | two sets of methods to draw text, the first set of which have <b><code>Text</code></b> | 
|  | in their method name, and will handle line delimiters and tabs and are used to | 
|  | implement an emulated Label. The second set of API methods have <b><code>String</code></b> | 
|  | in their method name, and no tab expansion or carriage return processing occurs, | 
|  | and are used for more sophisticated controls like the <code>StyledText </code>used | 
|  | by the Eclipse Java editor. | 
|  | <h2> <code>GC.drawText(String text, int x, int y);</code></h2> | 
|  | <code>Font font = new Font(display,"Arial",14,SWT.BOLD | SWT.ITALIC);</code> <br> | 
|  | <code>// ...</code> <br> | 
|  | <code>gc.drawText("Hello World",5,5);</code> <br> | 
|  | <code>gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));</code> <br> | 
|  | <code>gc.setFont(font);</code> <br> | 
|  | <code>gc.drawText("Hello\tThere\nWide\tWorld",5,25);</code> <br> | 
|  | <code>// ...</code> <br> | 
|  | <code>font.dispose();</code> | 
|  | <p><img src="images/TextHelloWorld.gif" height=108 width=200> | 
|  | <p>The drawText API processes the control characters \t as tab \n as a carriage | 
|  | return. | 
|  | <h2> <code>GC.drawString(String text, int x, int y);</code></h2> | 
|  | <code>Font font = new Font(display,"Arial",14,SWT.BOLD | SWT.ITALIC);</code> <br> | 
|  | <code>// ...</code> <br> | 
|  | <code>gc.drawString("Hello World",5,5);</code> <br> | 
|  | <code>gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));</code> <br> | 
|  | <code>gc.setFont(font);</code> <br> | 
|  | <code>gc.drawString("Hello\tThere\nWide\tWorld",5,25);</code> <br> | 
|  | <code>// ...</code> <br> | 
|  | <code>font.dispose()</code> | 
|  | <p><img src="images/StringHelloWorld.gif" height=106 width=304> <br> | 
|  | When drawString is used, the tab and carriage return characters are not processed | 
|  | <p>The size that a String occupies when it is drawn onto a GC is based on its | 
|  | contents and the font of the GC.  To determine the area that a String will | 
|  | occupy when it is drawn use the methods <code>GC.stringExtent(String text), </code>or<code> | 
|  | GC.textExtent(String text). </code>These return a Point whose x and y are the | 
|  | width and height required to render the String argument. | 
|  | <h2> <code>GC.drawText(String text, int x, int y, boolean isTransparent);</code></h2> | 
|  | When drawText(String text, int x, int y) is used the text is drawn in the GC's | 
|  | current foreground color.  If you are drawing on top of an area where you | 
|  | want the existing background to show through, then you can set the isTransparent | 
|  | argument to true.  This is useful if you are drawing on top of an image and | 
|  | you don't want the text to obscure the image's background. | 
|  | <p><code>Font font = new Font(display,"Arial",12,SWT.BOLD | SWT.ITALIC);</code> <br> | 
|  | <code>Image image = new Image(display,"C:/devEclipse_02/eclipse/plugins/org.eclipse.platform_2.0.2/eclipse_lg.gif");</code> | 
|  | <br> | 
|  | <code>GC gc = new GC(image);</code> <br> | 
|  | <code>gc.drawText("Hello World",5,5);</code> <br> | 
|  | <code>gc.setFont(font);</code> <br> | 
|  | <code>gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));</code> <br> | 
|  | <code>gc.drawText("Hello World",5,25,true);</code> <br> | 
|  | <code>gc.dispose();</code> <br> | 
|  | <code>image.dispose();</code> <br> | 
|  | <code>font.dispose();</code> | 
|  | <p><img src="images/TextHelloWorldTransparent.gif" height=182 width=159> <br> | 
|  |   | 
|  | <h2> <code>GC.drawText(String text, int x, int y, int flags);</code></h2> | 
|  | The flags are a bitmask of the constants SWT.DRAW_DELIMITER, SWT.DRAW_TAB, SWT.DRAW_TRANSPARENT | 
|  | and SWT.DRAW_MNEMONIC.  These determine whether or not \n is processed as | 
|  | a carriage return, \t as a tab expansion, whether background transparency is used, | 
|  | and whether & is processed as a mnemonic or a literal. | 
|  | <p><code>gc.drawImage(image,0,0);</code> <br> | 
|  | <code>gc.drawText("Hello\t&There\nWide\tWorld",5,5,SWT.DRAW_TRANSPARENT);</code> | 
|  | <br> | 
|  | <code>gc.drawText("Hello\t&There\nWide\tWorld",5,25,SWT.DRAW_DELIMITER | SWT.DRAW_TAB | 
|  | | SWT.DRAW_MNEMONIC );</code> | 
|  | <p><img src="images/TextFlags.gif" height=166 width=192> <br> | 
|  |   <br> | 
|  |   | 
|  | <h1> <a NAME="Filling shapes"></a>Filling shapes</h1> | 
|  | Whereas lines are drawn in the GC's foreground color, shapes are filled with the | 
|  | GC's background color. | 
|  | <h2> <code>GC.fillPolygon(int[]);</code></h2> | 
|  | <code>gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));</code> <br> | 
|  | <code>gc.fillPolygon(new int[] { 25,5,45,45,5,45 })</code> <br> | 
|  | <img src="images/PolygonFillClient.gif" height=96 width=164> | 
|  | <h2> <code>GC.fillRectangle(int x, int y, int width, int height);</code></h2> | 
|  | <code>gc.fillRectangle(5,5,90,45);</code> | 
|  | <p><img src="images/RectangleFillClient.gif" height=98 width=165> | 
|  | <p>When a rectangle is filled, the bottom and right edges are not included.  | 
|  | With the code above the origin point 5,5 is included in the filled blue rectangle, | 
|  | however the argument rectangle's bottom right corner of 95,50 (5+90 , 45+5) | 
|  | is outside the filled area.  The bottom right corner of the filled rectangle | 
|  | is at 94,49.  This is unlike the behavior for <code>drawRectangle(5,5,90,45)</code>, | 
|  | where the full shape is outlined so the bottom right corner is 95,50. | 
|  | <p>To illustrate this, the code below strokes a rectangle whose corners are 5,5 | 
|  | and 90,45 before filling it in cyan.  To ensure that the filling of the | 
|  | rectangle doesn't overwrite its drawn outline, the origin is offset to 6,6.  | 
|  | This moves the bottom right corner of the filled rectangle, however because | 
|  | it has already excluded the bottom and right edges it only needs to be inset | 
|  | by one to not overlap with the drawn rectangle. | 
|  | <p><code>gc.drawRectangle(5,5,90,45);</code> <br> | 
|  | <code>gc.setBackground(display.getSystemColor(SWT.COLOR_CYAN));</code> <br> | 
|  | <code>gc.fillRectangle(6,6,89,44);</code> | 
|  | <p><img src="images/RectangleStrokeFill.gif" height=111 width=195> | 
|  | <h2> <code>GC.fillRoundedRectangle(int x, int y, int width, int height, int arcWidth, | 
|  | int arcHeight);</code></h2> | 
|  | <code>gc.fillRoundRectangle(5,5,90,45,25,15);</code> | 
|  | <p><img src="images/RoundedRectangleFilledClient.gif" height=95 width=166> | 
|  | <p>Like the <code>GC.fillRectangle(...) </code>method, the bottom and right edges | 
|  | are excluded from the filled shape so the bottom right corner becomes 94,49 | 
|  | rather than 95,50. | 
|  | <h2> <code>GC.fillOval(int x, int y, int width, int height);</code></h2> | 
|  | <code>gc.fillOval(5,5,90,45);</code> | 
|  | <p><img src="images/OvalFilledClient.gif" height=93 width=167 align=ABSBOTTOM> | 
|  | <p>Like the other fill APIs, the bounding rectangle's bottom right corner is inset | 
|  | by one. | 
|  | <h2> <code>GC.fillArc(int x, int y, int widt4h., int height, int startAngle, int | 
|  | endAngle);</code></h2> | 
|  | <code>gc.fillArc(5,5,90,45,90,200);</code> <br> | 
|  | <img src="images/ArcFilledClient.gif" height=97 width=196> <br> | 
|  | The arguments to the <code>fillArc(...)</code> method are similar to the <code>drawArc(...)</code>, | 
|  | with the offset from an East axis to begin filling and the number of degrees to | 
|  | continue the arc in an anti-clockwise direction. However unlike the <code>drawArc(...)</code> | 
|  | whose bottom right corner of the bounding rectangle is the origin offset by the | 
|  | width and height, <code>fillArc(...)</code> follows the same pattern used by the other | 
|  | fill methods where the bottom and right edge are excluded and the corner inset | 
|  | by one. | 
|  | <h2> <code>GC.fillGradientRectangle(int x, int y, int width. int height, vertical | 
|  | boolean);</code></h2> | 
|  | This allows a rectangle to be filled with a gradient of coloring between the GC's | 
|  | foreground and background color.  The gradient can either be horizontal or | 
|  | vertical | 
|  | <p><code>gc.setBackgrouind(display,getSystemColor(SWT.COLOR_BLUE));</code> <br> | 
|  | <code>gc.fillGradientRectangle(5,5,90,45,false);</code> | 
|  | <p>This creates a horizontal gradient fill starting with the foreground color | 
|  | (black) on the left, and finishing with the background color (blue) on the right.  | 
|  | As with the other fill methods, the bottom and right edges are excluded so the | 
|  | bottom right corner becomes inset by 1. | 
|  | <p><img src="images/GradientFillFalse.gif" height=97 width=166> | 
|  | <p><code>gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));</code> <br> | 
|  | <code>gc.setForeground(display.getSystemColor(SWT.COLOR_CYAN));</code> <br> | 
|  | <code>gc.fillGradientRectangle(5,5,90,45,true);</code> | 
|  | <p>The vertical gradient begins at the top with the foreground color (cyan) and | 
|  | finishes at the bottom with the blue background color. | 
|  | <p><img src="images/GradientFillTrue.gif" height=100 width=166> | 
|  | <h1> <a NAME="XOR"></a>XOR</h1> | 
|  | When drawing occurs on a GC you are altering its pixel values that make up the | 
|  | graphic on the Drawable surface.  If you set the GC's XOR mode to true, then | 
|  | what occurs is that for each pixel the red, green and blue values of the source | 
|  | being drawn are XOR'd with the existing red, green and blue values and the result | 
|  | becomes the new destination pixel. <br> | 
|  |   | 
|  | <p><code>shell.setBackground(display.getSystemColor(SWT.COLOR_WHITE));</code> <br> | 
|  | <code>// ...</code> <br> | 
|  | <code>gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE));</code> <br> | 
|  | <code>gc.fillRectangle(5,5,90,45);</code> <br> | 
|  | <code>gc.setXORMode(true);</code> <br> | 
|  | <code>gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE));</code> <br> | 
|  | <code>gc.fillRectangle(20,20,50,50);</code> <br> | 
|  | <code>gc.setBackground(display.getSystemColor(SWT.COLOR_RED));</code> <br> | 
|  | <code>gc.fillOval(80,20,50,50);</code> | 
|  | <p><img src="images/XORFills.gif" height=117 width=276> | 
|  | <p>The filled rectangle has a background color of white (255,255,255).  When | 
|  | this is drawn over the blue (0,0,255) the XOR'd result is yellow (255,255,0).  | 
|  | The portion of the rectangle drawn over the white background (255,255,255) creates | 
|  | an XOR result of black (0,0,0). The filled oval has a background color or red | 
|  | (255,0,0).  When this is drawn over blue the resulting XOR value is purple | 
|  | (255,0,255), and when it is drawn over white the result is cyan (0,255,255); | 
|  | <h1> <a NAME="Drawing Images"></a>Drawing Images</h1> | 
|  | The class <code>org.eclipse.swt.graphics.Image</code> represents a graphic that has | 
|  | been prepared ready to be displayed on a device such as a Display or Printer.  | 
|  | The simplest way to create an image is to load it from a recognized file format.  | 
|  | Supported file formats are GIF, BMP (Windows format bitmap), JPG, PNG, and in | 
|  | newer Eclipse releases TIFF. | 
|  | <p><code>Image image = new Image(display,"C:/eclipse/eclipse/plugins/org.eclipse.platform_2.0.2/eclipse_lg.gif");</code> | 
|  | <h2> <code>GC.drawImage(Image image, int x, int y);</code></h2> | 
|  | Every image has a size that is determined by its bounds.  For example, the | 
|  | size of the image <code>eclipse_lg.gif </code>is 115,164 and can be determined by | 
|  | using the method <code>image.getBounds(). </code>When an image is drawn it will be | 
|  | shown at the width and height defined by its bounds.. | 
|  | <p><code>gc.drawImage(image,5,5);</code> <br> | 
|  | <img src="images/ImageClient.jpg" height=221 width=175> | 
|  | <h2> <code>GC.drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, | 
|  | int dstX, int dstY, int dstWidth, int dstHeight);</code></h2> | 
|  | Images can be drawn with different sizes from their original width and height, | 
|  | and also portions of images can be drawn. | 
|  | <p>The src coordinates are relative to image itself, so to draw the entire image | 
|  | use 0,0 and width and height set to the image bound's width and height.  | 
|  | The dst arguments represent where to draw the image on the GC, and what size | 
|  | to draw it at.  The original image is 115 by 164, so to stretch it to twice | 
|  | the width and half the height use the statement | 
|  | <p><code>gc.drawImage(image,0,0,115,164,5,5,230,82);</code> <br> | 
|  | <img src="images/ImageClientStretched.jpg" height=136 width=289> | 
|  | <p>Using the src coordinates allows you to specify that you want only a portion | 
|  | of the image drawn.  For example, if you only want a section from the top | 
|  | right area of the image drawn, you can use src coordinates of 20,0 and a width | 
|  | and height of 95,82.  The code below draws the destination rectangle with | 
|  | the same width and height (95,82) as the cropped area, however a different size | 
|  | could be used to stretch or shrink the image portion. | 
|  | <p><code>gc.drawImage(image,20,0,95,82,5,5,95,82);</code> | 
|  | <p><img src="images/ImageClipped.jpg" height=219 width=405> | 
|  | <p>Other images effects can be achieved, such as transparency, animation and alpha | 
|  | channel blending of images.  These are outside the scope of this article, | 
|  | however I hope to cover these in a future article. | 
|  | <h1> <a NAME="Understanding Images"></a>Conclusion</h1> | 
|  | This article has shown how a GC can be used to draw lines, text, and to fill shapes.  | 
|  | A GC can be created by passing the drawable into its constructor, such as an Image, | 
|  | or for a Control by using the <code>paintEvent</code> callback.  The API of a | 
|  | GC allows lines and shapes to be drawn in its foreground color and filled in its | 
|  | background color.  The general purpose Canvas control is optimized to allow | 
|  | drawing through its <code>paintEvent</code>, and it has a number of constructor style | 
|  | bits to control when paint events occur.  GC clipping allows you to control | 
|  | the region of the GC that visible drawing occurs on, and when drawing different | 
|  | line styles can be used, and text and images can be shown. | 
|  | <p><font size="-2">Java and all Java-based trademarks and logos are trademarks | 
|  | or registered trademarks of Sun Microsystems, Inc. in the United States, other | 
|  | countries, or both. </font> | 
|  | <p><font size="-2">Other company, product, and service names may be trademarks | 
|  | or service marks of others. </font> | 
|  | </body> | 
|  | </html> |