Logo Search packages:      
Sourcecode: eclipse version File versions  Download package

GC.java

/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.graphics;


import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.cairo.*;
import org.eclipse.swt.internal.motif.*;
import org.eclipse.swt.*;
 
/**
 * Class <code>GC</code> is where all of the drawing capabilities that are 
 * supported by SWT are located. Instances are used to draw on either an 
 * <code>Image</code>, a <code>Control</code>, or directly on a <code>Display</code>.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>LEFT_TO_RIGHT, RIGHT_TO_LEFT</dd>
 * </dl>
 * 
 * <p>
 * The SWT drawing coordinate system is the two-dimensional space with the origin
 * (0,0) at the top left corner of the drawing area and with (x,y) values increasing
 * to the right and downward respectively.
 * </p>
 * 
 * <p>
 * Application code must explicitly invoke the <code>GC.dispose()</code> 
 * method to release the operating system resources managed by each instance
 * when those instances are no longer required. This is <em>particularly</em>
 * important on Windows95 and Windows98 where the operating system has a limited
 * number of device contexts available.
 * </p>
 * 
 * <p>
 * Note: Only one of LEFT_TO_RIGHT and RIGHT_TO_LEFT may be specified.
 * </p>
 *
 * @see org.eclipse.swt.events.PaintEvent
 */
public final class GC extends Resource {
      /**
       * the handle to the OS device context
       * (Warning: This field is platform dependent)
       * <p>
       * <b>IMPORTANT:</b> This field is <em>not</em> part of the SWT
       * public API. It is marked public only so that it can be shared
       * within the packages provided by SWT. It is not available on all
       * platforms and should never be accessed from application code.
       * </p>
       */
      public int handle;
      
      Drawable drawable;
      GCData data;

      static final int[] LINE_DOT = new int[]{1, 1};
      static final int[] LINE_DASH = new int[]{3, 1};
      static final int[] LINE_DASHDOT = new int[]{3, 1, 1, 1};
      static final int[] LINE_DASHDOTDOT = new int[]{3, 1, 1, 1, 1, 1};
      static final int[] LINE_DOT_ZERO = new int[]{3, 3};
      static final int[] LINE_DASH_ZERO = new int[]{18, 6};
      static final int[] LINE_DASHDOT_ZERO = new int[]{9, 6, 3, 6};
      static final int[] LINE_DASHDOTDOT_ZERO = new int[]{9, 3, 3, 3, 3, 3};

GC() {
}
/**    
 * Constructs a new instance of this class which has been
 * configured to draw on the specified drawable. Sets the
 * foreground and background color in the GC to match those
 * in the drawable.
 * <p>
 * You must dispose the graphics context when it is no longer required. 
 * </p>
 * @param drawable the drawable to draw on
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
 *    <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
 *    <li>ERROR_INVALID_ARGUMENT
 *          - if the drawable is an image that is not a bitmap or an icon
 *          - if the drawable is an image or printer that is already selected
 *            into another graphics context</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
 * </ul>
 */
00096 public GC(Drawable drawable) {
      this(drawable, 0);
}
/**    
 * Constructs a new instance of this class which has been
 * configured to draw on the specified drawable. Sets the
 * foreground and background color in the GC to match those
 * in the drawable.
 * <p>
 * You must dispose the graphics context when it is no longer required. 
 * </p>
 * 
 * @param drawable the drawable to draw on
 * @param style the style of GC to construct
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
 *    <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
 *    <li>ERROR_INVALID_ARGUMENT
 *          - if the drawable is an image that is not a bitmap or an icon
 *          - if the drawable is an image or printer that is already selected
 *            into another graphics context</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
 * </ul>
 *  
 * @since 2.1.2
 */
00125 public GC(Drawable drawable, int style) {
      if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      GCData data = new GCData();
      data.style = checkStyle(style);
      int xGC = drawable.internal_new_GC(data);
      Device device = data.device;
      if (device == null) device = Device.getDevice();
      if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      this.device = data.device = device;
      init(drawable, data, xGC);
      if (device.tracking) device.new_Object(this);
}
static int checkStyle (int style) {
      if ((style & SWT.LEFT_TO_RIGHT) != 0) style &= ~SWT.RIGHT_TO_LEFT;
      return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
}
/**
 * Copies a rectangular area of the receiver at the source
 * position onto the receiver at the destination position.
 *
 * @param srcX the x coordinate in the receiver of the area to be copied
 * @param srcY the y coordinate in the receiver of the area to be copied
 * @param width the width of the area to copy
 * @param height the height of the area to copy
 * @param destX the x coordinate in the receiver of the area to copy to
 * @param destY the y coordinate in the receiver of the area to copy to
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
00156 public void copyArea(int x, int y, int width, int height, int destX, int destY) {
      copyArea(x, y, width, height, destX, destY, true);
}
/**
 * Copies a rectangular area of the receiver at the source
 * position onto the receiver at the destination position.
 *
 * @param srcX the x coordinate in the receiver of the area to be copied
 * @param srcY the y coordinate in the receiver of the area to be copied
 * @param width the width of the area to copy
 * @param height the height of the area to copy
 * @param destX the x coordinate in the receiver of the area to copy to
 * @param destY the y coordinate in the receiver of the area to copy to
 * @param paint if <code>true</code> paint events will be generated for old and obscured areas
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1 
 */
00177 public void copyArea(int x, int y, int width, int height, int destX, int destY, boolean paint) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width <= 0 || height <= 0) return;
      int deltaX = destX - x, deltaY = destY - y;
      if (deltaX == 0 && deltaY == 0) return;
      int xDisplay = data.display;
      int xDrawable = data.drawable;
      if (data.image == null && paint) OS.XSetGraphicsExposures (xDisplay, handle, true);
      OS.XCopyArea(xDisplay, xDrawable, xDrawable, handle, x, y, width, height, destX, destY);
      if (data.image == null && paint) {
            OS.XSetGraphicsExposures (xDisplay, handle, false);
            boolean disjoint = (destX + width < x) || (x + width < destX) || (destY + height < y) || (y + height < destY);
            if (disjoint) {
                  OS.XClearArea (xDisplay, xDrawable, x, y, width, height, true);
            } else {
                  if (deltaX != 0) {
                        int newX = destX - deltaX;
                        if (deltaX < 0) newX = destX + width;
                        OS.XClearArea (xDisplay, xDrawable, newX, y, Math.abs (deltaX), height, true);
                  }
                  if (deltaY != 0) {
                        int newY = destY - deltaY;
                        if (deltaY < 0) newY = destY + height;
                        OS.XClearArea (xDisplay, xDrawable, x, newY, width, Math.abs (deltaY), true);
                  }
            }
      }
}
/**
 * Copies a rectangular area of the receiver at the specified
 * position into the image, which must be of type <code>SWT.BITMAP</code>.
 *
 * @param image the image to copy into
 * @param x the x coordinate in the receiver of the area to be copied
 * @param y the y coordinate in the receiver of the area to be copied
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the image is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the image is not a bitmap or has been disposed</li> 
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
00221 public void copyArea(Image image, int x, int y) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (image.type != SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      Rectangle rect = image.getBounds();
      int xDisplay = data.display;
      int xGC = OS.XCreateGC(xDisplay, image.pixmap, 0, null);
      if (xGC == 0) SWT.error(SWT.ERROR_NO_HANDLES);
      OS.XSetSubwindowMode (xDisplay, xGC, OS.IncludeInferiors);
      OS.XCopyArea(xDisplay, data.drawable, image.pixmap, xGC, x, y, rect.width, rect.height, 0, 0);
      OS.XFreeGC(xDisplay, xGC);
}
/**
 * Disposes of the operating system resources associated with
 * the graphics context. Applications must dispose of all GCs
 * which they allocate.
 */
00238 public void dispose () {
      if (handle == 0) return;
      if (data.device.isDisposed()) return;

      int /*long*/ cairo = data.cairo;
      if (cairo != 0) Cairo.cairo_destroy(cairo);
      int /*long*/ matrix = data.matrix;
      if (matrix != 0) Cairo.cairo_matrix_destroy(matrix);
      int /*long*/ inverseMatrix = data.inverseMatrix;
      if (inverseMatrix != 0) Cairo.cairo_matrix_destroy(inverseMatrix);
      data.cairo = data.matrix = data.inverseMatrix = 0;

      /* Free resources */
      int clipRgn = data.clipRgn;
      if (clipRgn != 0) OS.XDestroyRegion(clipRgn);
      Image image = data.image;
      if (image != null) {
            image.memGC = null;
            if (image.transparentPixel != -1) image.createMask();
      }

      int renderTable = data.renderTable;
      if (renderTable != 0) OS.XmRenderTableFree(renderTable);
      int xmString = data.xmString;
      if (xmString != 0) OS.XmStringFree (xmString);
      int xmText = data.xmText;
      if (xmText != 0) OS.XmStringFree (xmText);
      int xmMnemonic = data.xmMnemonic;
      if (xmMnemonic != 0) OS.XmStringFree (xmMnemonic);

      /* Dispose the GC */
      Device device = data.device;
      if (drawable != null) drawable.internal_dispose_GC(handle, data);

      data.display = data.drawable = data.colormap = 
            data.clipRgn = data.renderTable = data.xmString = data.xmText = 
                  data.xmMnemonic = 0;
      data.font = null;
      drawable = null;
      handle = 0;
      data.image = null;
      if (device.tracking) device.dispose_Object(this);
      data.device = null;
      data = null;
}
/**
 * Draws the outline of a circular or elliptical arc 
 * within the specified rectangular area.
 * <p>
 * The resulting arc begins at <code>startAngle</code> and extends  
 * for <code>arcAngle</code> degrees, using the current color.
 * Angles are interpreted such that 0 degrees is at the 3 o'clock
 * position. A positive value indicates a counter-clockwise rotation
 * while a negative value indicates a clockwise rotation.
 * </p><p>
 * The center of the arc is the center of the rectangle whose origin 
 * is (<code>x</code>, <code>y</code>) and whose size is specified by the 
 * <code>width</code> and <code>height</code> arguments. 
 * </p><p>
 * The resulting arc covers an area <code>width + 1</code> pixels wide
 * by <code>height + 1</code> pixels tall.
 * </p>
 *
 * @param x the x coordinate of the upper-left corner of the arc to be drawn
 * @param y the y coordinate of the upper-left corner of the arc to be drawn
 * @param width the width of the arc to be drawn
 * @param height the height of the arc to be drawn
 * @param startAngle the beginning angle
 * @param arcAngle the angular extent of the arc, relative to the start angle
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
00312 public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      if (width == 0 || height == 0 || arcAngle == 0) return;
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_save(cairo);
            float offset = data.lineWidth == 0 || (data.lineWidth % 2) == 1 ? 0.5f : 0f;
            Cairo.cairo_translate(cairo, x + offset + width / 2f, y + offset + height / 2f);
            Cairo.cairo_scale(cairo, width / 2f, height / 2f);
            Cairo.cairo_set_line_width(cairo, Cairo.cairo_current_line_width(cairo) / (width / 2f));
            Cairo.cairo_arc_negative(cairo, 0, 0, 1, -startAngle * (float)Compatibility.PI / 180, -(startAngle + arcAngle) * (float)Compatibility.PI / 180);
            Cairo.cairo_stroke(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      OS.XDrawArc(data.display, data.drawable, handle, x, y, width, height, startAngle * 64, arcAngle * 64);
}
/** 
 * Draws a rectangle, based on the specified arguments, which has
 * the appearance of the platform's <em>focus rectangle</em> if the
 * platform supports such a notion, and otherwise draws a simple
 * rectangle in the receiver's foreground color.
 *
 * @param x the x coordinate of the rectangle
 * @param y the y coordinate of the rectangle
 * @param width the width of the rectangle
 * @param height the height of the rectangle
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawRectangle(int, int, int, int)
 */
00354 public void drawFocus (int x, int y, int width, int height) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      /*
      * When the drawable is not a widget, the highlight
      * color is zero.
      */
      int xDisplay = data.display;
      int xDrawable = data.drawable;
      int highlightColor = 0;
      int widget = OS.XtWindowToWidget (xDisplay, xDrawable);
      if (widget != 0) {
            int [] argList = {OS.XmNhighlightColor, 0};
            OS.XtGetValues (widget, argList, argList.length / 2);
            highlightColor = argList [1];
      }

      /* Draw the focus rectangle */
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      XGCValues values = new XGCValues ();
      OS.XGetGCValues (xDisplay, handle, OS.GCForeground, values);
      OS.XSetForeground (xDisplay, handle, highlightColor);
      OS.XDrawRectangle (xDisplay, xDrawable, handle, x, y, width - 1, height - 1);
      OS.XSetForeground (xDisplay, handle, values.foreground);
}
/**
 * Draws the given image in the receiver at the specified
 * coordinates.
 *
 * @param image the image to draw
 * @param x the x coordinate of where to draw
 * @param y the y coordinate of where to draw
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the image is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image</li>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
 * </ul>
 */
00404 public void drawImage(Image image, int x, int y) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true);
}

/**
 * Copies a rectangular area from the source image into a (potentially
 * different sized) rectangular area in the receiver. If the source
 * and destination areas are of differing sizes, then the source
 * area will be stretched or shrunk to fit the destination area
 * as it is copied. The copy fails if any part of the source rectangle
 * lies outside the bounds of the source image, or if any of the width
 * or height arguments are negative.
 *
 * @param image the source image
 * @param srcX the x coordinate in the source image to copy from
 * @param srcY the y coordinate in the source image to copy from
 * @param srcWidth the width in pixels to copy from the source
 * @param srcHeight the height in pixels to copy from the source
 * @param destX the x coordinate in the destination to copy to
 * @param destY the y coordinate in the destination to copy to
 * @param destWidth the width in pixels of the destination rectangle
 * @param destHeight the height in pixels of the destination rectangle
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the image is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
 *    <li>ERROR_INVALID_ARGUMENT - if any of the width or height arguments are negative.
 *    <li>ERROR_INVALID_ARGUMENT - if the source rectangle is not contained within the bounds of the source image</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
 * </ul>
 */
00443 public void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return;
      if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0 || destWidth < 0 || destHeight < 0) {
            SWT.error (SWT.ERROR_INVALID_ARGUMENT);
      }
      if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false);
}
void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
      int[] width = new int[1];
      int[] height = new int[1];
      int[] depth = new int[1];
      int[] unused = new int[1];
      OS.XGetGeometry(data.display, srcImage.pixmap, unused, unused, unused, width, height, unused, depth);
      int imgWidth = width[0];
      int imgHeight = height[0];
      if (simple) {
            srcWidth = destWidth = imgWidth;
            srcHeight = destHeight = imgHeight;
      } else {
            simple = srcX == 0 && srcY == 0 &&
                  srcWidth == destWidth && destWidth == imgWidth &&
                  srcHeight == destHeight && destHeight == imgHeight;
            if (srcX + srcWidth > imgWidth || srcY + srcHeight > imgHeight) {
                  SWT.error(SWT.ERROR_INVALID_ARGUMENT);
            }
      }     
      if (srcImage.alpha != -1 || srcImage.alphaData != null) {
            drawImageAlpha(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight, depth[0]);
      } else if (srcImage.transparentPixel != -1 || srcImage.mask != 0) {
            drawImageMask(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight, depth[0]);
      } else {
            drawImage(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight, depth[0]);
      }
}
void drawImageAlpha(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight, int depth) {
      /* Simple cases */
      if (srcImage.alpha == 0) return;
      if (srcImage.alpha == 255) {
            drawImage(srcImage, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, simple, imgWidth, imgHeight, depth);
            return;
      }

      /* Check the clipping */
      Rectangle rect = getClipping();
      rect = rect.intersection(new Rectangle(destX, destY, destWidth, destHeight));
      if (rect.isEmpty()) return;
      
      /* Optimization. Recalculate the src and dest rectangles so that
      * only the clipping area is drawn.
      */
      int sx1 = srcX + (((rect.x - destX) * srcWidth) / destWidth);
      int sx2 = srcX + ((((rect.x + rect.width) - destX) * srcWidth) / destWidth);
      int sy1 = srcY + (((rect.y - destY) * srcHeight) / destHeight);
      int sy2 = srcY + ((((rect.y + rect.height) - destY) * srcHeight) / destHeight);
      destX = rect.x;
      destY = rect.y;
      destWidth = rect.width;
      destHeight = rect.height;
      srcX = sx1;
      srcY = sy1;
      srcWidth = Math.max(1, sx2 - sx1);
      srcHeight = Math.max(1, sy2 - sy1);
      
      int xDisplay = data.display;
      int xDrawable = data.drawable;
      int xDestImagePtr = 0, xSrcImagePtr = 0;
      try {
            /* Get the background pixels */
            xDestImagePtr = OS.XGetImage(xDisplay, xDrawable, destX, destY, destWidth, destHeight, OS.AllPlanes, OS.ZPixmap);
            if (xDestImagePtr == 0) return;
            XImage xDestImage = new XImage();
            OS.memmove(xDestImage, xDestImagePtr, XImage.sizeof);
            byte[] destData = new byte[xDestImage.bytes_per_line * xDestImage.height];
            OS.memmove(destData, xDestImage.data, destData.length);     
      
            /* Get the foreground pixels */
            xSrcImagePtr = OS.XGetImage(xDisplay, srcImage.pixmap, srcX, srcY, srcWidth, srcHeight, OS.AllPlanes, OS.ZPixmap);
            if (xSrcImagePtr == 0) return;
            XImage xSrcImage = new XImage();
            OS.memmove(xSrcImage, xSrcImagePtr, XImage.sizeof);
            byte[] srcData = new byte[xSrcImage.bytes_per_line * xSrcImage.height];
            OS.memmove(srcData, xSrcImage.data, srcData.length);
            
            /* Compose the pixels */            
            if (xSrcImage.depth <= 8) {
                  XColor[] xcolors = data.device.xcolors;
                  if (xcolors == null) SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
                  byte[] reds = new byte[xcolors.length];
                  byte[] greens = new byte[xcolors.length];
                  byte[] blues = new byte[xcolors.length];
                  for (int i = 0; i < xcolors.length; i++) {
                        XColor color = xcolors[i];
                        if (color == null) continue;
                        reds[i] = (byte)((color.red >> 8) & 0xFF);
                        greens[i] = (byte)((color.green >> 8) & 0xFF);
                        blues[i] = (byte)((color.blue >> 8) & 0xFF);
                  }
                  ImageData.blit(ImageData.BLIT_ALPHA,
                        srcData, xSrcImage.bits_per_pixel, xSrcImage.bytes_per_line, xSrcImage.byte_order, 0, 0, srcWidth, srcHeight, reds, greens, blues,
                        srcImage.alpha, srcImage.alphaData, imgWidth, srcX, srcY,
                        destData, xDestImage.bits_per_pixel, xDestImage.bytes_per_line, xDestImage.byte_order, 0, 0, destWidth, destHeight, reds, greens, blues,
                        false, false);
            } else {
                  int srcRedMask = xSrcImage.red_mask;
                  int srcGreenMask = xSrcImage.green_mask;
                  int srcBlueMask = xSrcImage.blue_mask;
                  int destRedMask = xDestImage.red_mask;
                  int destGreenMask = xDestImage.green_mask;
                  int destBlueMask = xDestImage.blue_mask;
                  
                  /*
                  * Feature in X.  XGetImage does not retrieve the RGB masks if the drawable
                  * is a Pixmap.  The fix is to detect that the masks are not valid and use
                  * the default visual masks instead.
                  * 
                  * NOTE: It is safe to use the default Visual masks, since we always
                  * create images with these masks. 
                  */
                  int visual = OS.XDefaultVisual(xDisplay, OS.XDefaultScreen(xDisplay));
                  Visual xVisual = new Visual();
                  OS.memmove(xVisual, visual, Visual.sizeof);
                  if (srcRedMask == 0 && srcGreenMask == 0 && srcBlueMask == 0) {
                        srcRedMask = xVisual.red_mask;
                        srcGreenMask = xVisual.green_mask;
                        srcBlueMask = xVisual.blue_mask;
                  }
                  if (destRedMask == 0 && destGreenMask == 0 && destBlueMask == 0) {
                        destRedMask = xVisual.red_mask;
                        destGreenMask = xVisual.green_mask;
                        destBlueMask = xVisual.blue_mask;
                  }
                  
                  ImageData.blit(ImageData.BLIT_ALPHA,
                        srcData, xSrcImage.bits_per_pixel, xSrcImage.bytes_per_line, xSrcImage.byte_order, 0, 0, srcWidth, srcHeight, srcRedMask, srcGreenMask, srcBlueMask,
                        srcImage.alpha, srcImage.alphaData, imgWidth, srcX, srcY,
                        destData, xDestImage.bits_per_pixel, xDestImage.bytes_per_line, xDestImage.byte_order, 0, 0, destWidth, destHeight, destRedMask, destGreenMask, destBlueMask,
                        false, false);
            }
            
            /* Draw the composed pixels */
            OS.memmove(xDestImage.data, destData, destData.length);
            OS.XPutImage(xDisplay, xDrawable, handle, xDestImagePtr, 0, 0, destX, destY, destWidth, destHeight);
      } finally {
            if (xSrcImagePtr != 0) OS.XDestroyImage(xSrcImagePtr);
            if (xDestImagePtr != 0) OS.XDestroyImage(xDestImagePtr);
      }
}
void drawImageMask(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight, int depth) {
      int xDisplay = data.display;
      int xDrawable = data.drawable;
      /* Generate the mask if necessary. */
      if (srcImage.transparentPixel != -1) srcImage.createMask();
      int colorPixmap = 0, maskPixmap = 0;
      int foreground = 0x00000000;
      if (simple || (srcWidth == destWidth && srcHeight == destHeight)) {
            colorPixmap = srcImage.pixmap;
            maskPixmap = srcImage.mask;
      } else {
            /* Stretch the color and mask*/
            int xImagePtr = scalePixmap(xDisplay, srcImage.pixmap, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false, false);
            if (xImagePtr != 0) {
                  int xMaskPtr = scalePixmap(xDisplay, srcImage.mask, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false, false);
                  if (xMaskPtr != 0) {
                        /* Create color scaled pixmaps */
                        colorPixmap = OS.XCreatePixmap(xDisplay, xDrawable, destWidth, destHeight, depth);
                        int tempGC = OS.XCreateGC(xDisplay, colorPixmap, 0, null);
                        OS.XPutImage(xDisplay, colorPixmap, tempGC, xImagePtr, 0, 0, 0, 0, destWidth, destHeight);
                        OS.XFreeGC(xDisplay, tempGC);
            
                        /* Create mask scaled pixmaps */
                        maskPixmap = OS.XCreatePixmap(xDisplay, xDrawable, destWidth, destHeight, 1);
                        tempGC = OS.XCreateGC(xDisplay, maskPixmap, 0, null);
                        OS.XPutImage(xDisplay, maskPixmap, tempGC, xMaskPtr, 0, 0, 0, 0, destWidth, destHeight);
                        OS.XFreeGC(xDisplay, tempGC);

                        OS.XDestroyImage(xMaskPtr);
                  }
                  OS.XDestroyImage(xImagePtr);
            }
            
            /* Change the source rectangle */
            srcX = srcY = 0;
            srcWidth = destWidth;
            srcHeight = destHeight;

            foreground = ~foreground;
      }
      
      /* Do the blts */
      if (colorPixmap != 0 && maskPixmap != 0) {
            XGCValues values = new XGCValues();
            OS.XGetGCValues(xDisplay, handle, OS.GCForeground | OS. GCBackground | OS.GCFunction, values);
            OS.XSetFunction(xDisplay, handle, OS.GXxor);
            OS.XCopyArea(xDisplay, colorPixmap, xDrawable, handle, srcX, srcY, srcWidth, srcHeight, destX, destY);
            OS.XSetForeground(xDisplay, handle, foreground);
            OS.XSetBackground(xDisplay, handle, ~foreground);
            OS.XSetFunction(xDisplay, handle, OS.GXand);
            OS.XCopyPlane(xDisplay, maskPixmap, xDrawable, handle, srcX, srcY, srcWidth, srcHeight, destX, destY, 1);
            OS.XSetFunction(xDisplay, handle, OS.GXxor);
            OS.XCopyArea(xDisplay, colorPixmap, xDrawable, handle, srcX, srcY, srcWidth, srcHeight, destX, destY);
            OS.XSetForeground(xDisplay, handle, values.foreground);
            OS.XSetBackground(xDisplay, handle, values.background);
            OS.XSetFunction(xDisplay, handle, values.function);
      }

      /* Destroy scaled pixmaps */
      if (colorPixmap != 0 && srcImage.pixmap != colorPixmap) OS.XFreePixmap(xDisplay, colorPixmap);
      if (maskPixmap != 0 && srcImage.mask != maskPixmap) OS.XFreePixmap(xDisplay, maskPixmap);
      /* Destroy the image mask if the there is a GC created on the image */
      if (srcImage.transparentPixel != -1 && srcImage.memGC != null) srcImage.destroyMask();
}
void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple, int imgWidth, int imgHeight, int depth) {
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            srcImage.createSurface();
            Cairo.cairo_save(cairo);
            //TODO - draw a piece of the image
//          if (srcX != 0 || srcY != 0) {
//                Cairo.cairo_rectangle(cairo, destX, destY, destWidth, destHeight);
//                Cairo.cairo_clip(cairo);
//                Cairo.cairo_new_path(cairo);
//          }
            Cairo.cairo_translate(cairo, destX - srcX, destY - srcY);
            if (srcWidth != destWidth || srcHeight != destHeight) {
                  Cairo.cairo_scale(cairo, destWidth / (float)srcWidth,  destHeight / (float)srcHeight);
            }
            int filter = Cairo.CAIRO_FILTER_GOOD;
            switch (data.interpolation) {
                  case SWT.DEFAULT: filter = Cairo.CAIRO_FILTER_GOOD; break;
                  case SWT.NONE: filter = Cairo.CAIRO_FILTER_NEAREST; break;
                  case SWT.LOW: filter = Cairo.CAIRO_FILTER_FAST; break;
                  case SWT.HIGH: filter = Cairo.CAIRO_FILTER_BEST; break;
            }
            Cairo.cairo_surface_set_filter(srcImage.surface, filter);
            Cairo.cairo_show_surface(cairo, srcImage.surface, imgWidth, imgHeight);
            Cairo.cairo_restore(cairo);
            return;
      }
      int xDisplay = data.display;
      int xDrawable = data.drawable;
      /* Simple case: no stretching */
      if ((srcWidth == destWidth) && (srcHeight == destHeight)) {
            OS.XCopyArea(xDisplay, srcImage.pixmap, xDrawable, handle, srcX, srcY, srcWidth, srcHeight, destX, destY);
            return;
      }
      
      /* Streching case */
      int xImagePtr = scalePixmap(xDisplay, srcImage.pixmap, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight, false, false);
      if (xImagePtr != 0) {
            OS.XPutImage(xDisplay, xDrawable, handle, xImagePtr, 0, 0, destX, destY, destWidth, destHeight);
            OS.XDestroyImage(xImagePtr);
      }
}
static int scalePixmap(int display, int pixmap, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean flipX, boolean flipY) {
      int xSrcImagePtr = OS.XGetImage(display, pixmap, srcX, srcY, srcWidth, srcHeight, OS.AllPlanes, OS.ZPixmap);
      if (xSrcImagePtr == 0) return 0;
      XImage xSrcImage = new XImage();
      OS.memmove(xSrcImage, xSrcImagePtr, XImage.sizeof);
      byte[] srcData = new byte[xSrcImage.bytes_per_line * xSrcImage.height];
      OS.memmove(srcData, xSrcImage.data, srcData.length);
      OS.XDestroyImage(xSrcImagePtr);
      int xImagePtr = 0;
      int visual = OS.XDefaultVisual(display, OS.XDefaultScreen(display));
      switch (xSrcImage.bits_per_pixel) {
            case 1:
            case 4:
            case 8: {
                  int format = xSrcImage.bits_per_pixel == 1 ? OS.XYBitmap : OS.ZPixmap;
                  xImagePtr = OS.XCreateImage(display, visual, xSrcImage.depth, format, 0, 0, destWidth, destHeight, xSrcImage.bitmap_pad, 0);
                  if (xImagePtr == 0) return 0;
                  XImage xImage = new XImage();
                  OS.memmove(xImage, xImagePtr, XImage.sizeof);
                  int bufSize = xImage.bytes_per_line * xImage.height;
                  if (bufSize < 0) {
                        OS.XDestroyImage(xImagePtr);
                        return 0;
                  } 
                  int bufPtr = OS.XtMalloc(bufSize);
                  xImage.data = bufPtr;
                  OS.memmove(xImagePtr, xImage, XImage.sizeof);
                  byte[] buf = new byte[bufSize];
                  int srcOrder = xSrcImage.bits_per_pixel == 1 ? xSrcImage.bitmap_bit_order : xSrcImage.byte_order;
                  int destOrder = xImage.bits_per_pixel == 1 ? xImage.bitmap_bit_order : xImage.byte_order;
                  ImageData.blit(ImageData.BLIT_SRC,
                        srcData, xSrcImage.bits_per_pixel, xSrcImage.bytes_per_line, srcOrder, 0, 0, srcWidth, srcHeight, null, null, null,
                        ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
                        buf, xImage.bits_per_pixel, xImage.bytes_per_line, destOrder, 0, 0, destWidth, destHeight, null, null, null,
                        flipX, flipY);
                  OS.memmove(bufPtr, buf, bufSize);
                  break;
            }
            case 16:
            case 24:
            case 32: {
                  xImagePtr = OS.XCreateImage(display, visual, xSrcImage.depth, OS.ZPixmap, 0, 0, destWidth, destHeight, xSrcImage.bitmap_pad, 0);
                  if (xImagePtr == 0) return 0;
                  XImage xImage = new XImage();
                  OS.memmove(xImage, xImagePtr, XImage.sizeof);
                  int bufSize = xImage.bytes_per_line * xImage.height;
                  if (bufSize < 0) {
                        OS.XDestroyImage(xImagePtr);
                        return 0;
                  } 
                  int bufPtr = OS.XtMalloc(bufSize);
                  xImage.data = bufPtr;
                  OS.memmove(xImagePtr, xImage, XImage.sizeof);
                  byte[] buf = new byte[bufSize];
                  ImageData.blit(ImageData.BLIT_SRC,
                        srcData, xSrcImage.bits_per_pixel, xSrcImage.bytes_per_line, xSrcImage.byte_order, 0, 0, srcWidth, srcHeight, 0, 0, 0,
                        ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
                        buf, xImage.bits_per_pixel, xImage.bytes_per_line, xImage.byte_order, 0, 0, destWidth, destHeight, 0, 0, 0,
                        flipX, flipY);
                  OS.memmove(bufPtr, buf, bufSize);
                  break;
            }
      }
      return xImagePtr;
}
/** 
 * Draws a line, using the foreground color, between the points 
 * (<code>x1</code>, <code>y1</code>) and (<code>x2</code>, <code>y2</code>).
 *
 * @param x1 the first point's x coordinate
 * @param y1 the first point's y coordinate
 * @param x2 the second point's x coordinate
 * @param y2 the second point's y coordinate
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
00777 public void drawLine (int x1, int y1, int x2, int y2) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            float offset = data.lineWidth == 0 || (data.lineWidth % 2) == 1 ? 0.5f : 0f;
            Cairo.cairo_move_to(cairo, x1 + offset, y1 + offset);
            Cairo.cairo_line_to(cairo, x2 + offset, y2 + offset);
            Cairo.cairo_stroke(cairo);
            return;
      }
      OS.XDrawLine (data.display, data.drawable, handle, x1, y1, x2, y2);
}
/** 
 * Draws the outline of an oval, using the foreground color,
 * within the specified rectangular area.
 * <p>
 * The result is a circle or ellipse that fits within the 
 * rectangle specified by the <code>x</code>, <code>y</code>, 
 * <code>width</code>, and <code>height</code> arguments. 
 * </p><p> 
 * The oval covers an area that is <code>width + 1</code> 
 * pixels wide and <code>height + 1</code> pixels tall.
 * </p>
 *
 * @param x the x coordinate of the upper left corner of the oval to be drawn
 * @param y the y coordinate of the upper left corner of the oval to be drawn
 * @param width the width of the oval to be drawn
 * @param height the height of the oval to be drawn
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
00810 public void drawOval(int x, int y, int width, int height) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_save(cairo);
            float offset = data.lineWidth == 0 || (data.lineWidth % 2) == 1 ? 0.5f : 0f;
            Cairo.cairo_translate(cairo, x + offset + width / 2f, y + offset + height / 2f);
            Cairo.cairo_scale(cairo, width / 2f, height / 2f);
            Cairo.cairo_set_line_width(cairo, Cairo.cairo_current_line_width(cairo) / (width / 2f));
            Cairo.cairo_arc_negative(cairo, 0, 0, 1, 0, -2 * (float)Compatibility.PI);
            Cairo.cairo_stroke(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      OS.XDrawArc(data.display, data.drawable, handle, x, y, width, height, 0, 23040);
}
/** 
 * Draws the path described by the parameter.
 *
 * @param path the path to draw
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Path
 * 
 * @since 3.1
 */
00851 public void drawPath(Path path) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (path.handle == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      initCairo();
      int /*long*/ cairo = data.cairo;
      Cairo.cairo_save(cairo);
      float offset = data.lineWidth == 0 || (data.lineWidth % 2) == 1 ? 0.5f : 0f;
      Cairo.cairo_translate(cairo, offset, offset);
      Cairo.cairo_add_path(cairo, path.handle);
      Cairo.cairo_stroke(cairo);
      Cairo.cairo_restore(cairo);
}
/** 
 * Draws a pixel, using the foreground color, at the specified
 * point (<code>x</code>, <code>y</code>).
 * <p>
 * Note that the receiver's line attributes do not affect this
 * operation.
 * </p>
 *
 * @param x the point's x coordinate
 * @param y the point's y coordinate
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *  
 * @since 3.0
 */
00881 public void drawPoint (int x, int y) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_rectangle(cairo, x, y, 1, 1);
            Cairo.cairo_fill(cairo);
            return;
      }
      OS.XDrawPoint(data.display, data.drawable, handle, x, y);
}
/** 
 * Draws the closed polygon which is defined by the specified array
 * of integer coordinates, using the receiver's foreground color. The array 
 * contains alternating x and y values which are considered to represent
 * points which are the vertices of the polygon. Lines are drawn between
 * each consecutive pair, and between the first pair and last pair in the
 * array.
 *
 * @param pointArray an array of alternating x and y values which are the vertices of the polygon
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
00908 public void drawPolygon(int[] pointArray) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            drawPolyline(cairo, pointArray, true);
            Cairo.cairo_stroke(cairo);
            return;
      }
      
      // Motif does not have a native drawPolygon() call. Instead we ensure 
      // that the first and last points are the same and call drawPolyline().
      
      int length = pointArray.length;

      // Need at least 3 points to define the polygon. If 2 or fewer points
      // passed in, it is either a line or point so just call drawPolyline().
      // Check what happens when XOR is implemented. We may not be able to
      // do this optimization.
      
      if (length < 4) {
                  drawPolyline(pointArray);
                  return;
      }

      // If first and last points are the same, the polygon is already closed.
      // Just call drawPolyline().
      //
      // Check what happens when XOR is implemented. We may not be able to
      // do this optimization.
      
      if (pointArray[0] == pointArray[length - 2] && (pointArray[1] == pointArray[length - 1])) {
            drawPolyline(pointArray);
            return;
      }

      // Grow the list of points by one element and make sure the first and last
      // points are the same. This will close the polygon and we can use the
      // drawPolyline() call. 
            
      int newPoints[] = new int[length + 2];
      for (int i = 0; i < length ; i++) 
            newPoints[i] = pointArray[i];
      newPoints[length] = pointArray[0];
      newPoints[length + 1] = pointArray[1];

      drawPolyline(newPoints);
}
/** 
 * Draws the polyline which is defined by the specified array
 * of integer coordinates, using the receiver's foreground color. The array 
 * contains alternating x and y values which are considered to represent
 * points which are the corners of the polyline. Lines are drawn between
 * each consecutive pair, but not between the first pair and last pair in
 * the array.
 *
 * @param pointArray an array of alternating x and y values which are the corners of the polyline
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the point array is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
00973 public void drawPolyline(int[] pointArray) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            drawPolyline(cairo, pointArray, false);
            Cairo.cairo_stroke(cairo);
            return;
      }
      short[] xPoints = new short[pointArray.length];
      for (int i = 0; i<pointArray.length;i++) {
            xPoints[i] = (short) pointArray[i];
      }
      OS.XDrawLines(data.display,data.drawable,handle,xPoints,xPoints.length / 2, OS.CoordModeOrigin);
}
void drawPolyline(int /*long*/ cairo, int[] pointArray, boolean close) {
      int count = pointArray.length / 2;
      if (count == 0) return;
      float offset = data.lineWidth == 0 || (data.lineWidth % 2) == 1 ? 0.5f : 0f;
      Cairo.cairo_move_to(cairo, pointArray[0] + offset, pointArray[1] + offset);
      for (int i = 1, j=2; i < count; i++, j += 2) {
            Cairo.cairo_line_to(cairo, pointArray[j] + offset, pointArray[j + 1] + offset);
      }
      if (close) Cairo.cairo_close_path(cairo);
}
/** 
 * Draws the outline of the rectangle specified by the arguments,
 * using the receiver's foreground color. The left and right edges
 * of the rectangle are at <code>x</code> and <code>x + width</code>. 
 * The top and bottom edges are at <code>y</code> and <code>y + height</code>. 
 *
 * @param x the x coordinate of the rectangle to be drawn
 * @param y the y coordinate of the rectangle to be drawn
 * @param width the width of the rectangle to be drawn
 * @param height the height of the rectangle to be drawn
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01013 public void drawRectangle (int x, int y, int width, int height) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            float offset = data.lineWidth == 0 || (data.lineWidth % 2) == 1 ? 0.5f : 0f;
            Cairo.cairo_rectangle(cairo, x + offset, y + offset, width, height);
            Cairo.cairo_stroke(cairo);
            return;
      }
      OS.XDrawRectangle (data.display, data.drawable, handle, x, y, width, height);
}
/** 
 * Draws the outline of the specified rectangle, using the receiver's
 * foreground color. The left and right edges of the rectangle are at
 * <code>rect.x</code> and <code>rect.x + rect.width</code>. The top 
 * and bottom edges are at <code>rect.y</code> and 
 * <code>rect.y + rect.height</code>. 
 *
 * @param rect the rectangle to draw
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01048 public void drawRectangle (Rectangle rect) {
      if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      drawRectangle (rect.x, rect.y, rect.width, rect.height);
}
/** 
 * Draws the outline of the round-cornered rectangle specified by 
 * the arguments, using the receiver's foreground color. The left and
 * right edges of the rectangle are at <code>x</code> and <code>x + width</code>. 
 * The top and bottom edges are at <code>y</code> and <code>y + height</code>.
 * The <em>roundness</em> of the corners is specified by the 
 * <code>arcWidth</code> and <code>arcHeight</code> arguments, which
 * are respectively the width and height of the ellipse used to draw
 * the corners.
 *
 * @param x the x coordinate of the rectangle to be drawn
 * @param y the y coordinate of the rectangle to be drawn
 * @param width the width of the rectangle to be drawn
 * @param height the height of the rectangle to be drawn
 * @param arcWidth the width of the arc
 * @param arcHeight the height of the arc
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01073 public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int nx = x;
      int ny = y;
      int nw = width;
      int nh = height;
      int naw = arcWidth;
      int nah = arcHeight;
      if (nw < 0) {
            nw = 0 - nw;
            nx = nx - nw;
      }
      if (nh < 0) {
            nh = 0 - nh;
            ny = ny - nh;
      }
      if (naw < 0) naw = 0 - naw;
      if (nah < 0) nah = 0 - nah;
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            float naw2 = naw / 2f;
            float nah2 = nah / 2f;
            float fw = nw / naw2;
            float fh = nh / nah2;
            Cairo.cairo_new_path(cairo);
            Cairo.cairo_save(cairo);
            float offset = data.lineWidth == 0 || (data.lineWidth % 2) == 1 ? 0.5f : 0f;
            Cairo.cairo_translate(cairo, nx + offset, ny + offset);
            Cairo.cairo_scale(cairo, naw2, nah2);
            Cairo.cairo_move_to(cairo, fw - 1, 0);
//          Cairo.cairo_arc_to(cairo, 0, 0, 0, 1, 1);
//          Cairo.cairo_arc_to(cairo, 0, fh, 1, fh, 1);
//          Cairo.cairo_arc_to(cairo, fw, fh, fw, fh - 1, 1);
//          Cairo.cairo_arc_to(cairo, fw, 0, fw - 1, 0, 1);
            Cairo.cairo_close_path(cairo);
            Cairo.cairo_stroke(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      int naw2 = naw / 2;
      int nah2 = nah / 2;
      int xDisplay = data.display;
      int xDrawable = data.drawable;
      if (nw > naw) {
            if (nh > nah) {
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx, ny, naw, nah, 5760, 5760);
                  OS.XDrawLine(xDisplay, xDrawable, handle, nx + naw2, ny, nx + nw - naw2, ny);
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx + nw - naw, ny, naw, nah, 0, 5760);
                  OS.XDrawLine(xDisplay, xDrawable, handle, nx + nw, ny + nah2, nx + nw, ny + nh - nah2);
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx + nw - naw, ny + nh - nah, naw, nah, 17280, 5760);
                  OS.XDrawLine(xDisplay,xDrawable,handle, nx + naw2, ny + nh, nx + nw - naw2, ny + nh);
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx, ny + nh - nah, naw, nah, 11520, 5760);
                  OS.XDrawLine(xDisplay, xDrawable, handle, nx, ny + nah2, nx, ny + nh - nah2);
            } else {
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx, ny, naw, nh, 5760, 11520);
                  OS.XDrawLine(xDisplay, xDrawable, handle, nx + naw2, ny, nx + nw - naw2, ny);
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx + nw - naw, ny, naw, nh, 17280, 11520);
                  OS.XDrawLine(xDisplay,xDrawable,handle, nx + naw2, ny + nh, nx + nw - naw2, ny + nh);
            }
      } else {
            if (nh > nah) {
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx, ny, nw, nah, 0, 11520);
                  OS.XDrawLine(xDisplay, xDrawable, handle, nx + nw, ny + nah2, nx + nw, ny + nh - nah2);
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx, ny + nh - nah, nw, nah, 11520, 11520);
                  OS.XDrawLine(xDisplay,xDrawable,handle, nx, ny + nah2, nx, ny + nh - nah2);
            } else {
                  OS.XDrawArc(xDisplay, xDrawable, handle, nx, ny, nw, nh, 0, 23040);
            }
      }
}
/** 
 * Draws the given string, using the receiver's current font and
 * foreground color. No tab expansion or carriage return processing
 * will be performed. The background of the rectangular area where
 * the string is being drawn will be filled with the receiver's
 * background color.
 *
 * @param string the string to be drawn
 * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
 * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01161 public void drawString (String string, int x, int y) {
      drawString(string, x, y, false);
}
/** 
 * Draws the given string, using the receiver's current font and
 * foreground color. No tab expansion or carriage return processing
 * will be performed. If <code>isTransparent</code> is <code>true</code>,
 * then the background of the rectangular area where the string is being
 * drawn will not be modified, otherwise it will be filled with the
 * receiver's background color.
 *
 * @param string the string to be drawn
 * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
 * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
 * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01184 public void drawString (String string, int x, int y, boolean isTransparent) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (string.length() == 0) return;
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            //TODO - honor isTransparent
            cairo_font_extents_t extents = new cairo_font_extents_t();
            Cairo.cairo_current_font_extents(cairo, extents);
            double baseline = y + extents.ascent;
            Cairo.cairo_move_to(cairo, x, baseline);
            byte[] buffer = Converter.wcsToMbcs(null, string, true);
            Cairo.cairo_text_path(cairo, buffer);
            Cairo.cairo_fill(cairo);
            return;
      }
      setString(string);
      if (isTransparent) {
            OS.XmStringDraw (data.display, data.drawable, data.font.handle, data.xmString, handle, x, y, 0x7FFFFFFF, OS.XmALIGNMENT_BEGINNING, 0, null);
      } else {
            OS.XmStringDrawImage (data.display, data.drawable, data.font.handle, data.xmString, handle, x, y, 0x7FFFFFFF, OS.XmALIGNMENT_BEGINNING, 0, null);
      }                 
}
void createRenderTable() {
      int xDisplay = data.display;
      int fontList = data.font.handle;    
      /* Get the width of the tabs */
      byte[] buffer = {(byte)' ', 0};
      int xmString = OS.XmStringCreate(buffer, OS.XmFONTLIST_DEFAULT_TAG);
      int tabWidth = OS.XmStringWidth(fontList, xmString) * 8;
      OS.XmStringFree(xmString);
      
      /* Create the tab list */
      int [] tabs = new int[16]; 
      int tab = OS.XmTabCreate(tabWidth, (byte) OS.XmPIXELS, (byte) OS.XmRELATIVE, (byte) OS.XmALIGNMENT_BEGINNING, null);
      for (int i = 0; i < tabs.length; i++) tabs[i] = tab;
      int tabList = OS.XmTabListInsertTabs(0, tabs, tabs.length, 0);    
            
      /* Create a font context to iterate over the elements in the font list */
      int[] fontBuffer = new int[1];
      if (!OS.XmFontListInitFontContext(fontBuffer, fontList)) {
            SWT.error(SWT.ERROR_NO_HANDLES);
      }
      int context = fontBuffer[0], fontListEntry = 0;
      int[] renditions = new int[4]; int renditionCount = 0;      
            
      /* Create a rendition for each entry in the font list */
      while ((fontListEntry = OS.XmFontListNextEntry(context)) != 0) {
            int fontPtr = OS.XmFontListEntryGetFont(fontListEntry, fontBuffer);
            int fontType = (fontBuffer [0] == 0) ? OS.XmFONT_IS_FONT : OS.XmFONT_IS_FONTSET;
            if (fontPtr == 0) SWT.error(SWT.ERROR_NO_HANDLES);
            int [] argList = {
                  OS.XmNtabList, tabList,
                  OS.XmNfont, fontPtr,
                  OS.XmNfontType, fontType,
            };
            int rendition = OS.XmRenditionCreate(data.device.shellHandle, OS.XmFONTLIST_DEFAULT_TAG, argList, argList.length / 2);
            renditions[renditionCount++] = rendition;
            if (renditionCount == renditions.length) {
                  int[] newArray = new int[renditions.length + 4];
                  System.arraycopy(newArray, 0, renditions, 0, renditionCount);
                  renditions = newArray;
            }
      }     
      OS.XmFontListFreeFontContext(context);
      OS.XmTabFree(tab);
      OS.XmTabListFree(tabList);
      
      /* Create the render table from the renditions */
      data.renderTable = OS.XmRenderTableAddRenditions(0, renditions, renditionCount, OS.XmMERGE_REPLACE);
      for (int i = 0; i < renditionCount; i++) OS.XmRenditionFree(renditions[i]);
}
/** 
 * Draws the given string, using the receiver's current font and
 * foreground color. Tab expansion and carriage return processing
 * are performed. The background of the rectangular area where
 * the text is being drawn will be filled with the receiver's
 * background color.
 *
 * @param string the string to be drawn
 * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
 * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01274 public void drawText (String string, int x, int y) {
      drawText(string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
}
/** 
 * Draws the given string, using the receiver's current font and
 * foreground color. Tab expansion and carriage return processing
 * are performed. If <code>isTransparent</code> is <code>true</code>,
 * then the background of the rectangular area where the text is being
 * drawn will not be modified, otherwise it will be filled with the
 * receiver's background color.
 *
 * @param string the string to be drawn
 * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
 * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
 * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01297 public void drawText (String string, int x, int y, boolean isTransparent) {
      int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB;
      if (isTransparent) flags |= SWT.DRAW_TRANSPARENT;
      drawText(string, x, y, flags);
}
/** 
 * Draws the given string, using the receiver's current font and
 * foreground color. Tab expansion, line delimiter and mnemonic
 * processing are performed according to the specified flags. If
 * <code>flags</code> includes <code>DRAW_TRANSPARENT</code>,
 * then the background of the rectangular area where the text is being
 * drawn will not be modified, otherwise it will be filled with the
 * receiver's background color.
 * <p>
 * The parameter <code>flags</code> may be a combination of:
 * <dl>
 * <dt><b>DRAW_DELIMITER</b></dt>
 * <dd>draw multiple lines</dd>
 * <dt><b>DRAW_TAB</b></dt>
 * <dd>expand tabs</dd>
 * <dt><b>DRAW_MNEMONIC</b></dt>
 * <dd>underline the mnemonic character</dd>
 * <dt><b>DRAW_TRANSPARENT</b></dt>
 * <dd>transparent background</dd>
 * </dl>
 * </p>
 *
 * @param string the string to be drawn
 * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
 * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
 * @param flags the flags specifing how to process the text
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01336 public void drawText (String string, int x, int y, int flags) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (string.length() == 0) return;
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            //TODO - honor flags
            cairo_font_extents_t extents = new cairo_font_extents_t();
            Cairo.cairo_current_font_extents(cairo, extents);
            double baseline = y + extents.ascent;
            Cairo.cairo_move_to(cairo, x, baseline);
            byte[] buffer = Converter.wcsToMbcs(null, string, true);
            Cairo.cairo_text_path(cairo, buffer);
            Cairo.cairo_fill(cairo);
            return;
      }
      setText(string, flags);
      int xDisplay = data.display;
      int xDrawable = data.drawable;
      if (data.image != null) OS.XtRegisterDrawable (xDisplay, xDrawable, data.device.shellHandle);
      int xmMnemonic = data.xmMnemonic;
      if (xmMnemonic != 0) {
            OS.XmStringDrawUnderline(xDisplay, xDrawable, data.renderTable, data.xmText, handle, x, y, 0x7FFFFFFF, OS.XmALIGNMENT_BEGINNING, 0, null, xmMnemonic);
      } else {
            if ((flags & SWT.DRAW_TRANSPARENT) != 0) {
                  OS.XmStringDraw(xDisplay, xDrawable, data.renderTable, data.xmText, handle, x, y, 0x7FFFFFFF, OS.XmALIGNMENT_BEGINNING, 0, null);
            } else {
                  OS.XmStringDrawImage(xDisplay, xDrawable, data.renderTable, data.xmText, handle, x, y, 0x7FFFFFFF, OS.XmALIGNMENT_BEGINNING, 0, null);
            }
      }
      if (data.image != null) OS.XtUnregisterDrawable (xDisplay, xDrawable);
}
/**
 * Compares the argument to the receiver, and returns true
 * if they represent the <em>same</em> object using a class
 * specific comparison.
 *
 * @param object the object to compare with this object
 * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
 *
 * @see #hashCode
 */
01378 public boolean equals (Object object) {
      if (object == this) return true;
      if (!(object instanceof GC)) return false;
      return handle == ((GC)object).handle;
}
/**
 * Fills the interior of a circular or elliptical arc within
 * the specified rectangular area, with the receiver's background
 * color.
 * <p>
 * The resulting arc begins at <code>startAngle</code> and extends  
 * for <code>arcAngle</code> degrees, using the current color.
 * Angles are interpreted such that 0 degrees is at the 3 o'clock
 * position. A positive value indicates a counter-clockwise rotation
 * while a negative value indicates a clockwise rotation.
 * </p><p>
 * The center of the arc is the center of the rectangle whose origin 
 * is (<code>x</code>, <code>y</code>) and whose size is specified by the 
 * <code>width</code> and <code>height</code> arguments. 
 * </p><p>
 * The resulting arc covers an area <code>width + 1</code> pixels wide
 * by <code>height + 1</code> pixels tall.
 * </p>
 *
 * @param x the x coordinate of the upper-left corner of the arc to be filled
 * @param y the y coordinate of the upper-left corner of the arc to be filled
 * @param width the width of the arc to be filled
 * @param height the height of the arc to be filled
 * @param startAngle the beginning angle
 * @param arcAngle the angular extent of the arc, relative to the start angle
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawArc
 */
01415 public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      if (width == 0 || height == 0 || arcAngle == 0) return;
      int xDisplay = data.display;
      XGCValues values = new XGCValues ();
      OS.XGetGCValues (xDisplay, handle, OS.GCForeground | OS.GCBackground, values);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            XColor color = new XColor();
            color.pixel = values.background;
            OS.XQueryColor(xDisplay, data.colormap, color);
            Cairo.cairo_save(cairo);
            if (data.backgroundPattern != null) {
                  Cairo.cairo_set_pattern(cairo, data.backgroundPattern.handle);
            } else {
                  Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
            }
            Cairo.cairo_translate(cairo, x + width / 2f, y + height / 2f);
            Cairo.cairo_scale(cairo, width / 2f, height / 2f);
            Cairo.cairo_arc_negative(cairo, 0, 0, 1, -startAngle * (float)Compatibility.PI / 180,  -(startAngle + arcAngle) * (float)Compatibility.PI / 180);
            Cairo.cairo_line_to(cairo, 0, 0);
            Cairo.cairo_fill(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      OS.XSetForeground (xDisplay, handle, values.background);
      OS.XFillArc(xDisplay, data.drawable, handle, x, y, width, height, startAngle * 64, arcAngle * 64);
      OS.XSetForeground (xDisplay, handle, values.foreground);
}

/**
 * Fills the interior of the specified rectangle with a gradient
 * sweeping from left to right or top to bottom progressing
 * from the receiver's foreground color to its background color.
 *
 * @param x the x coordinate of the rectangle to be filled
 * @param y the y coordinate of the rectangle to be filled
 * @param width the width of the rectangle to be filled, may be negative
 *        (inverts direction of gradient if horizontal)
 * @param height the height of the rectangle to be filled, may be negative
 *        (inverts direction of gradient if vertical)
 * @param vertical if true sweeps from top to bottom, else 
 *        sweeps from left to right
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawRectangle(int, int, int, int)
 */
01473 public void fillGradientRectangle(int x, int y, int width, int height, boolean vertical) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if ((width == 0) || (height == 0)) return;
      int xDisplay = data.display;
      int xScreenNum = OS.XDefaultScreen(xDisplay);
      XGCValues values = new XGCValues();
      int fromColor, toColor;
      OS.XGetGCValues(xDisplay, handle, OS.GCForeground | OS.GCBackground, values);
      fromColor = values.foreground;
      toColor = values.background;
      boolean swapColors = false;
      if (width < 0) {
            x += width; width = -width;
            if (! vertical) swapColors = true;
      }
      if (height < 0) {
            y += height; height = -height;
            if (vertical) swapColors = true;
      }
      if (swapColors) {
            final int t = fromColor;
            fromColor = toColor;
            toColor = t;
      }
      if (fromColor == toColor) {
            OS.XFillRectangle(xDisplay, data.drawable, handle, x, y, width, height);
            return;
      }
      /* X Window deals with a virtually limitless array of color formats
       * but we only distinguish between paletted and direct modes
       */   
      final int xScreen = OS.XDefaultScreenOfDisplay(xDisplay);
      final int xVisual = OS.XDefaultVisual(xDisplay, xScreenNum);
      Visual visual = new Visual();
      OS.memmove(visual, xVisual, Visual.sizeof);
      final int depth = OS.XDefaultDepthOfScreen(xScreen);
      final boolean directColor = (depth > 8);

      // This code is intentionally commented since elsewhere in SWT we
      // assume that depth <= 8 means we are in a paletted mode though
      // this is not always the case.
      //final boolean directColor = (visual.c_class == OS.TrueColor) || (visual.c_class == OS.DirectColor);

      XColor xColor = new XColor();
      xColor.pixel = fromColor;
      OS.XQueryColor(xDisplay, data.colormap, xColor);
      final RGB fromRGB = new RGB((xColor.red & 0xffff) >>> 8, (xColor.green & 0xffff) >>> 8, (xColor.blue & 0xffff) >>> 8);
      xColor.pixel = toColor;
      OS.XQueryColor(xDisplay, data.colormap, xColor);
      final RGB toRGB = new RGB((xColor.red & 0xffff) >>> 8, (xColor.green & 0xffff) >>> 8, (xColor.blue & 0xffff) >>> 8);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            int /*long*/ pattern;
            if (vertical) {
                  pattern = Cairo.cairo_pattern_create_linear (0.0, 0.0, 0.0, 1.0);
            } else {
                  pattern = Cairo.cairo_pattern_create_linear (0.0, 0.0, 1.0, 0.0);
            }
            Cairo.cairo_pattern_add_color_stop (pattern, 0, fromRGB.red / 255f, fromRGB.green / 255f, fromRGB.blue / 255f, 1);
            Cairo.cairo_pattern_add_color_stop (pattern, 1, toRGB.red / 255f, toRGB.green / 255f, toRGB.blue / 255f, 1);
            Cairo.cairo_save(cairo);
            Cairo.cairo_translate(cairo, x, y);
            Cairo.cairo_scale(cairo, width, height);
            Cairo.cairo_rectangle(cairo, 0, 0, 1, 1);
            Cairo.cairo_set_pattern(cairo, pattern);
            Cairo.cairo_fill(cairo);
            Cairo.cairo_restore(cairo);
            Cairo.cairo_pattern_destroy(pattern);
            return;
      }
      final int redBits, greenBits, blueBits;
      if (directColor) {
            // RGB mapped display
            redBits = getChannelWidth(visual.red_mask);
            greenBits = getChannelWidth(visual.green_mask);
            blueBits = getChannelWidth(visual.blue_mask);
      } else {
            // Index display
            redBits = greenBits = blueBits = 0;
      }
      ImageData.fillGradientRectangle(this, data.device,
            x, y, width, height, vertical, fromRGB, toRGB,
            redBits, greenBits, blueBits);
}

/**
 * Computes the required channel width (depth) from a mask.
 */
01561 static int getChannelWidth(int mask) {
      int width = 0;
      while (mask != 0) {
            width += (mask & 1);
            mask >>>= 1;
      }
      return width;
}

/** 
 * Fills the interior of an oval, within the specified
 * rectangular area, with the receiver's background
 * color.
 *
 * @param x the x coordinate of the upper left corner of the oval to be filled
 * @param y the y coordinate of the upper left corner of the oval to be filled
 * @param width the width of the oval to be filled
 * @param height the height of the oval to be filled
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawOval
 */
01586 public void fillOval (int x, int y, int width, int height) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      int display = data.display;
      XGCValues values = new XGCValues ();
      OS.XGetGCValues (display, handle, OS.GCForeground | OS.GCBackground, values);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            XColor color = new XColor();
            color.pixel = values.background;
            OS.XQueryColor(display, data.colormap, color);
            Cairo.cairo_save(cairo);
            if (data.backgroundPattern != null) {
                  Cairo.cairo_set_pattern(cairo, data.backgroundPattern.handle);
            } else {
                  Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
            }
            Cairo.cairo_translate(cairo, x + width / 2f, y + height / 2f);
            Cairo.cairo_scale(cairo, width / 2f, height / 2f);
            Cairo.cairo_arc_negative(cairo, 0, 0, 1, 0, 2 * (float)Compatibility.PI);
            Cairo.cairo_fill(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      OS.XSetForeground (display, handle, values.background);
      OS.XFillArc (display, data.drawable, handle, x, y, width, height, 0, 23040);
      OS.XSetForeground (display, handle, values.foreground);
}
/** 
 * Fills the path described by the parameter.
 *
 * @param path the path to fill
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Path
 * 
 * @since 3.1
 */
01638 public void fillPath (Path path) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (path.handle == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      initCairo();
      int display = data.display;
      XGCValues values = new XGCValues ();
      OS.XGetGCValues (display, handle, OS.GCForeground | OS.GCBackground, values);
      XColor color = new XColor();
      color.pixel = values.background;
      OS.XQueryColor(display, data.colormap, color);
      int /*long*/ cairo = data.cairo;
      Cairo.cairo_save(cairo);
      if (data.backgroundPattern != null) {
            Cairo.cairo_set_pattern(cairo, data.backgroundPattern.handle);
      } else {
            Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
      }
      Cairo.cairo_add_path(cairo, path.handle);
      Cairo.cairo_fill(cairo);
      Cairo.cairo_restore(cairo);
}
/** 
 * Fills the interior of the closed polygon which is defined by the
 * specified array of integer coordinates, using the receiver's
 * background color. The array contains alternating x and y values
 * which are considered to represent points which are the vertices of
 * the polygon. Lines are drawn between each consecutive pair, and
 * between the first pair and last pair in the array.
 *
 * @param pointArray an array of alternating x and y values which are the vertices of the polygon
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawPolygon    
 */
01679 public void fillPolygon(int[] pointArray) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      int xDisplay = data.display;
      XGCValues values = new XGCValues ();
      OS.XGetGCValues (xDisplay, handle, OS.GCForeground | OS.GCBackground, values);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            XColor color = new XColor();
            color.pixel = values.background;
            OS.XQueryColor(xDisplay, data.colormap, color);
            Cairo.cairo_save(cairo);
            if (data.backgroundPattern != null) {
                  Cairo.cairo_set_pattern(cairo, data.backgroundPattern.handle);
            } else {
                  Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
            }
            drawPolyline(cairo, pointArray, true);
            Cairo.cairo_fill(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      short[] xPoints = new short[pointArray.length];
      for (int i = 0; i<pointArray.length;i++) {
            xPoints[i] = (short) pointArray[i];
      }
      OS.XSetForeground (xDisplay, handle, values.background);
      OS.XFillPolygon(xDisplay, data.drawable, handle,xPoints, xPoints.length / 2, OS.Complex, OS.CoordModeOrigin);
      OS.XSetForeground (xDisplay, handle, values.foreground);
}
/** 
 * Fills the interior of the rectangle specified by the arguments,
 * using the receiver's background color. 
 *
 * @param x the x coordinate of the rectangle to be filled
 * @param y the y coordinate of the rectangle to be filled
 * @param width the width of the rectangle to be filled
 * @param height the height of the rectangle to be filled
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawRectangle(int, int, int, int)
 */
01724 public void fillRectangle (int x, int y, int width, int height) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      int xDisplay = data.display;
      XGCValues values = new XGCValues ();
      OS.XGetGCValues (xDisplay, handle, OS.GCForeground | OS.GCBackground, values);
      int /*long*/ cairo = data.cairo; 
      if (cairo != 0) {
            XColor color = new XColor();
            color.pixel = values.background;
            OS.XQueryColor(xDisplay, data.colormap, color);
            Cairo.cairo_save(cairo);
            if (data.backgroundPattern != null) {
                  Cairo.cairo_set_pattern(cairo, data.backgroundPattern.handle);
            } else {
                  Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
            }
            Cairo.cairo_rectangle(cairo, x, y, width, height);
            Cairo.cairo_fill(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      OS.XSetForeground (xDisplay, handle, values.background);
      OS.XFillRectangle (xDisplay, data.drawable, handle, x, y, width, height);
      OS.XSetForeground (xDisplay, handle, values.foreground);
}
/** 
 * Fills the interior of the specified rectangle, using the receiver's
 * background color. 
 *
 * @param rect the rectangle to be filled
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawRectangle(int, int, int, int)
 */
01772 public void fillRectangle (Rectangle rect) {
      if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      fillRectangle(rect.x, rect.y, rect.width, rect.height);
}
/** 
 * Fills the interior of the round-cornered rectangle specified by 
 * the arguments, using the receiver's background color. 
 *
 * @param x the x coordinate of the rectangle to be filled
 * @param y the y coordinate of the rectangle to be filled
 * @param width the width of the rectangle to be filled
 * @param height the height of the rectangle to be filled
 * @param arcWidth the width of the arc
 * @param arcHeight the height of the arc
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #drawRoundRectangle
 */
01793 public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int nx = x;
      int ny = y;
      int nw = width;
      int nh = height;
      int naw = arcWidth;
      int nah = arcHeight;
      if (nw < 0) {
            nw = 0 - nw;
            nx = nx - nw;
      }
      if (nh < 0) {
            nh = 0 - nh;
            ny = ny -nh;
      }
      if (naw < 0) naw = 0 - naw;
      if (nah < 0) nah = 0 - nah;
      int xDisplay = data.display;
      XGCValues values = new XGCValues ();
      OS.XGetGCValues(xDisplay, handle, OS.GCForeground | OS.GCBackground, values);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            float naw2 = naw / 2f;
            float nah2 = nah / 2f;
            float fw = nw / naw2;
            float fh = nh / nah2;
            XColor color = new XColor();
            color.pixel = values.background;
            OS.XQueryColor(xDisplay, data.colormap, color);
            Cairo.cairo_save(cairo);
            if (data.backgroundPattern != null) {
                  Cairo.cairo_set_pattern(cairo, data.backgroundPattern.handle);
            } else {
                  Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
            }
            Cairo.cairo_translate(cairo, nx, ny);
            Cairo.cairo_scale(cairo, naw2, nah2);
            Cairo.cairo_move_to(cairo, fw - 1, 0);
//          Cairo.cairo_arc_to(cairo, 0, 0, 0, 1, 1);
//          Cairo.cairo_arc_to(cairo, 0, fh, 1, fh, 1);
//          Cairo.cairo_arc_to(cairo, fw, fh, fw, fh - 1, 1);
//          Cairo.cairo_arc_to(cairo, fw, 0, fw - 1, 0, 1);
            Cairo.cairo_close_path(cairo);
            Cairo.cairo_stroke(cairo);
            Cairo.cairo_restore(cairo);
            return;
      }
      int naw2 = naw / 2;
      int nah2 = nah / 2;
      int xDrawable = data.drawable;
      OS.XSetForeground(xDisplay, handle, values.background);
      if (nw > naw) {
            if (nh > nah) {
                  OS.XFillArc(xDisplay, xDrawable, handle, nx, ny, naw, nah, 5760, 5760);
                  OS.XFillRectangle(xDisplay, xDrawable, handle, nx + naw2, ny, nw - naw2 * 2, nah2);
                  OS.XFillArc(xDisplay, xDrawable, handle, nx + nw - naw, ny, naw, nah, 0, 5760);
                  OS.XFillRectangle(xDisplay, xDrawable, handle, nx, ny + nah2, nw, nh - nah2 * 2);
                  OS.XFillArc(xDisplay, xDrawable, handle, nx + nw - naw, ny + nh - nah, naw, nah, 17280, 5760);
                  OS.XFillRectangle(xDisplay, xDrawable, handle, nx + naw2, ny + nh - nah2, nw - naw2 * 2, nah2);
                  OS.XFillArc(xDisplay, xDrawable, handle, nx, ny + nh - nah, naw, nah, 11520, 5760);
            } else {
                  OS.XFillArc(xDisplay, xDrawable, handle, nx, ny, naw, nh, 5760, 11520);
                  OS.XFillRectangle(xDisplay, xDrawable, handle, nx + naw2, ny, nw - naw2 * 2, nh);
                  OS.XFillArc(xDisplay, xDrawable, handle, nx + nw - naw, ny, naw, nh, 17280, 11520);
            }
      } else {
            if (nh > nah) {
                  OS.XFillArc(xDisplay, xDrawable, handle, nx, ny, nw, nah, 0, 11520);
                  OS.XFillRectangle(xDisplay, xDrawable, handle, nx, ny + nah2, nw, nh - nah2 * 2);
                  OS.XFillArc(xDisplay, xDrawable, handle, nx, ny + nh - nah, nw, nah, 11520, 11520);
            } else {
                  OS.XFillArc(xDisplay, xDrawable, handle, nx, ny, nw, nh, 0, 23040);
            }
      }
      OS.XSetForeground(xDisplay, handle, values.foreground);
}
char fixMnemonic(char[] text) {
      char mnemonic=0;
      int i=0, j=0;
      while (i < text.length) {
            if ((text [j++] = text [i++]) == '&') {
                  if (i == text.length) {continue;}
                  if (text [i] == '&') {i++; continue;}
                  if (mnemonic == 0) mnemonic = text [i];
                  j--;
            }
      }
      while (j < text.length) text [j++] = 0;
      return mnemonic;
}
/**
 * Returns the <em>advance width</em> of the specified character in
 * the font which is currently selected into the receiver.
 * <p>
 * The advance width is defined as the horizontal distance the cursor
 * should move after printing the character in the selected font.
 * </p>
 *
 * @param ch the character to measure
 * @return the distance in the x direction to move past the character before painting the next
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
01899 public int getAdvanceWidth(char ch) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int fontList  = data.font.handle;
      byte[] charBuffer = Converter.wcsToMbcs(getCodePage (), new char[] { ch }, false);
      int val = charBuffer[0] & 0xFF;
      /* Create a font context to iterate over each element in the font list */
      int[] buffer = new int[1];
      if (!OS.XmFontListInitFontContext(buffer, fontList)) {
            SWT.error(SWT.ERROR_NO_HANDLES);
      }
      int context = buffer[0];
      XFontStruct fontStruct = new XFontStruct();
      XCharStruct charStruct = new XCharStruct();
      int fontListEntry;
      int[] fontStructPtr = new int[1];
      int[] fontNamePtr = new int[1];
      /* Go through each entry in the font list. */
      while ((fontListEntry = OS.XmFontListNextEntry(context)) != 0) {
            int fontPtr = OS.XmFontListEntryGetFont(fontListEntry, buffer);
            if (buffer[0] == 0) {
                  OS.memmove(fontStruct, fontPtr, XFontStruct.sizeof);
                  /* FontList contains a single font */
                  if (fontStruct.min_byte1 == 0 && fontStruct.max_byte1 == 0) {
                        /* Single byte fontStruct */
                        if (fontStruct.min_char_or_byte2 <= val && val <= fontStruct.max_char_or_byte2) {
                              /* The font contains the character */
                              int charWidth = 0;
                              int perCharPtr = fontStruct.per_char;     
                              if (perCharPtr == 0) {
                                    /*
                                     * If perCharPtr is 0 then all glyphs in the font have
                                     * the same width as the font's maximum width.
                                     */
                                     charWidth = fontStruct.max_bounds_width;
                              } else {
                                    OS.memmove(charStruct, perCharPtr + ((val - fontStruct.min_char_or_byte2) * XCharStruct.sizeof), XCharStruct.sizeof);
                                    charWidth = charStruct.width;
                              } 
                              if (charWidth != 0) {
                                    OS.XmFontListFreeFontContext(context);
                                    return charWidth;
                              }
                        }
                  } else {
                        /* Double byte fontStruct */
                        int charsPerRow = fontStruct.max_char_or_byte2 - fontStruct.min_char_or_byte2 + 1;
                        int row = 0;
                        if (charBuffer.length > 1) row = charBuffer[1] - fontStruct.min_byte1;
                        int col = charBuffer[0] - fontStruct.min_char_or_byte2;
                        if (row <= fontStruct.max_byte1 && col <= fontStruct.max_char_or_byte2) {
                              /* The font contains the character */
                              int charWidth = 0;
                              int perCharPtr = fontStruct.per_char;     
                              if (perCharPtr == 0) {
                                    /*
                                     * If perCharPtr is 0 then all glyphs in the font have
                                     * the same width as the font's maximum width.
                                     */
                                     charWidth = fontStruct.max_bounds_width;
                              } else {
                                    int offset = row * charsPerRow + col;
                                    OS.memmove(charStruct, perCharPtr + offset * XCharStruct.sizeof, XCharStruct.sizeof);
                                    charWidth = charStruct.width;
                              }
                              if (charWidth != 0) {
                                    OS.XmFontListFreeFontContext(context);
                                    return charWidth;
                              }
                        }
                  } 
            } else { 
                  /* FontList contains a fontSet */
                  int nFonts = OS.XFontsOfFontSet(fontPtr, fontStructPtr, fontNamePtr);
                  int [] fontStructs = new int[nFonts];
                  OS.memmove(fontStructs, fontStructPtr[0], nFonts * 4);
                  /* Go through each fontStruct in the font set */
                  for (int i = 0; i < nFonts; i++) { 
                        OS.memmove(fontStruct, fontStructs[i], XFontStruct.sizeof);
                        if (fontStruct.min_byte1 == 0 && fontStruct.max_byte1 == 0) {
                              /* Single byte fontStruct */
                              if (fontStruct.min_char_or_byte2 <= val && val <= fontStruct.max_char_or_byte2) {
                                    /* The font contains the character */
                                    int charWidth = 0;
                                    int perCharPtr = fontStruct.per_char;     
                                    if (perCharPtr == 0) {
                                          /*
                                           * If perCharPtr is 0 then all glyphs in the font have
                                           * the same width as the font's maximum width.
                                           */
                                           charWidth = fontStruct.max_bounds_width;
                                    } else {
                                          OS.memmove(charStruct, perCharPtr + (val - fontStruct.min_char_or_byte2 * XCharStruct.sizeof), XCharStruct.sizeof);
                                          charWidth = charStruct.width;
                                    }
                                    if (charWidth != 0) {
                                          OS.XmFontListFreeFontContext(context);
                                          return charWidth;
                                    }
                              }
                        } else {
                              /* Double byte fontStruct */
                              int charsPerRow = fontStruct.max_char_or_byte2 - fontStruct.min_char_or_byte2 + 1;
                              int row = 0;
                              if (charBuffer.length > 1) row = charBuffer[1] - fontStruct.min_byte1;
                              int col = charBuffer[0] - fontStruct.min_char_or_byte2;
                              if (row <= fontStruct.max_byte1 && col <= fontStruct.max_char_or_byte2) {
                                    /* The font contains the character */
                                    int charWidth = 0;
                                    int perCharPtr = fontStruct.per_char;     
                                    if (perCharPtr == 0) {
                                          /*
                                           * If perCharPtr is 0 then all glyphs in the font have
                                           * the same width as the font's maximum width.
                                           */
                                           charWidth = fontStruct.max_bounds_width;
                                    } else {
                                          int offset = row * charsPerRow + col;
                                          OS.memmove(charStruct, perCharPtr + offset * XCharStruct.sizeof, XCharStruct.sizeof);
                                          charWidth = charStruct.width;
                                    }
                                    if (charWidth != 0) {
                                          OS.XmFontListFreeFontContext(context);
                                          return charWidth;
                                    }
                              }
                        } 
                  }
            }
      }
      OS.XmFontListFreeFontContext(context);
      return 0;
}
/**
 * Returns <code>true</code> if receiver is using the operating system's
 * advanced graphics subsystem.  Otherwise, <code>false</code> is returned
 * to indicate that normal graphics are in use.
 * <p>
 * Advanced graphics may not be installed for the operating system.  In this
 * case, <code>false</code> is always returned.  Some operating system have
 * only one graphics subsystem.  If this subsystem supports advanced graphics,
 * then <code>true</code> is always returned.  If any graphics operation such
 * as alpha, antialias, patterns, interpolation, paths, clipping or transformation
 * has caused the receiver to switch from regular to advanced graphics mode,
 * <code>true</code> is returned.  If the receiver has been explicitly switched
 * to advanced mode and this mode is supported, <code>true</code> is returned.
 * </p>
 *
 * @return the advanced value
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see #setAdvanced
 * @since 3.1
 */
02055 public boolean getAdvanced() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return data.cairo != 0;
}
/**
 * Returns the receiver's alpha value.
 *
 * @return the alpha value
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1
 */
02070 public int getAlpha() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (data.cairo == 0) return 0xFF;
      return (int)(Cairo.cairo_current_alpha(data.cairo) * 255);
}
/**
 * Returns the receiver's anti-aliasing setting value, which will be
 * one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code> or
 * <code>SWT.ON</code>. Note that this controls anti-aliasing for all
 * <em>non-text drawing</em> operations.
 *
 * @return the anti-aliasing setting
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see #getTextAntialias
 * 
 * @since 3.1
 */
02091 public int getAntialias() {
    if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
    if (data.cairo != 0) return SWT.ON;
    return data.antialias;
}
/** 
 * Returns the background color.
 *
 * @return the receiver's background color
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02105 public Color getBackground() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int xDisplay = data.display;
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCBackground, values);
      XColor xColor = new XColor();
      xColor.pixel = values.background;
      OS.XQueryColor(xDisplay,data.colormap,xColor);
      return Color.motif_new(data.device, xColor);
      
}
/** 
 * Returns the background pattern. The default value is
 * <code>null</code>.
 *
 * @return the receiver's background pattern
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Pattern
 * 
 * @since 3.1
 */
02130 public Pattern getBackgroundPattern() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return data.backgroundPattern;
}
/**
 * Returns the width of the specified character in the font
 * selected into the receiver. 
 * <p>
 * The width is defined as the space taken up by the actual
 * character, not including the leading and tailing whitespace
 * or overhang.
 * </p>
 *
 * @param ch the character to measure
 * @return the width of the character
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02150 public int getCharWidth(char ch) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int fontList = data.font.handle;
      byte[] charBuffer = Converter.wcsToMbcs(getCodePage (), new char[] { ch }, false);
      int val = charBuffer[0] & 0xFF;
      /* Create a font context to iterate over each element in the font list */
      int[] buffer = new int[1];
      if (!OS.XmFontListInitFontContext(buffer, fontList)) {
            SWT.error(SWT.ERROR_NO_HANDLES);
      }
      int context = buffer[0];
      XFontStruct fontStruct = new XFontStruct();
      XCharStruct charStruct = new XCharStruct();
      int fontListEntry;
      int[] fontStructPtr = new int[1];
      int[] fontNamePtr = new int[1];
      /* Go through each entry in the font list. */
      while ((fontListEntry = OS.XmFontListNextEntry(context)) != 0) {
            int fontPtr = OS.XmFontListEntryGetFont(fontListEntry, buffer);
            if (buffer[0] == 0) {
                  OS.memmove(fontStruct, fontPtr, XFontStruct.sizeof);
                  /* FontList contains a single font */
                  if (fontStruct.min_byte1 == 0 && fontStruct.max_byte1 == 0) {
                        /* Single byte fontStruct */
                        if (fontStruct.min_char_or_byte2 <= val && val <= fontStruct.max_char_or_byte2) {
                              /* The font contains the character */
                              int charWidth = 0;
                              int lBearing = 0;
                              int rBearing = 0;
                              int perCharPtr = fontStruct.per_char;     
                              if (perCharPtr == 0) {
                                    /*
                                     * If perCharPtr is 0 then all glyphs in the font have
                                     * the same width and left/right bearings as the font.
                                     */
                                    charWidth = fontStruct.max_bounds_width;
                                    lBearing = fontStruct.min_bounds_lbearing;
                                    rBearing = fontStruct.max_bounds_rbearing;
                              } else {
                                    OS.memmove(charStruct, perCharPtr + ((val - fontStruct.min_char_or_byte2) * XCharStruct.sizeof), XCharStruct.sizeof);
                                    charWidth = charStruct.width;
                                    lBearing = charStruct.lbearing;
                                    rBearing = charStruct.rbearing;
                              }
                              if (charWidth != 0) {
                                    OS.XmFontListFreeFontContext(context);
                                    return rBearing - lBearing;
                              }
                        }
                  } else {
                        /* Double byte fontStruct */
                        int charsPerRow = fontStruct.max_char_or_byte2 - fontStruct.min_char_or_byte2 + 1;
                        int row = 0;
                        if (charBuffer.length > 1) row = charBuffer[1] - fontStruct.min_byte1;
                        int col = charBuffer[0] - fontStruct.min_char_or_byte2;
                        if (row <= fontStruct.max_byte1 && col <= fontStruct.max_char_or_byte2) {
                              /* The font contains the character */
                              int charWidth = 0;
                              int lBearing = 0;
                              int rBearing = 0;
                              int perCharPtr = fontStruct.per_char;     
                              if (perCharPtr == 0) {
                                    /*
                                     * If perCharPtr is 0 then all glyphs in the font have
                                     * the same width and left/right bearings as the font.
                                     */
                                    charWidth = fontStruct.max_bounds_width;
                                    lBearing = fontStruct.min_bounds_lbearing;
                                    rBearing = fontStruct.max_bounds_rbearing;
                              } else {
                                    int offset = row * charsPerRow + col;
                                    OS.memmove(charStruct, perCharPtr + offset * XCharStruct.sizeof, XCharStruct.sizeof);
                                    charWidth = charStruct.width;
                                    lBearing = charStruct.lbearing;
                                    rBearing = charStruct.rbearing;
                              }
                              if (charWidth != 0) {
                                    OS.XmFontListFreeFontContext(context);
                                    return rBearing - lBearing;
                              }
                        }
                  } 
            } else { 
                  /* FontList contains a fontSet */
                  int nFonts = OS.XFontsOfFontSet(fontPtr, fontStructPtr, fontNamePtr);
                  int [] fontStructs = new int[nFonts];
                  OS.memmove(fontStructs, fontStructPtr[0], nFonts * 4);
                  /* Go through each fontStruct in the font set */
                  for (int i = 0; i < nFonts; i++) { 
                        OS.memmove(fontStruct, fontStructs[i], XFontStruct.sizeof);
                        if (fontStruct.min_byte1 == 0 && fontStruct.max_byte1 == 0) {
                              /* Single byte fontStruct */
                              if (fontStruct.min_char_or_byte2 <= val && val <= fontStruct.max_char_or_byte2) {
                                    /* The font contains the character */
                                    int charWidth = 0;
                                    int lBearing = 0;
                                    int rBearing = 0;
                                    int perCharPtr = fontStruct.per_char;     
                                    if (perCharPtr == 0) {
                                          /*
                                           * If perCharPtr is 0 then all glyphs in the font have
                                           * the same width and left/right bearings as the font.
                                           */
                                          charWidth = fontStruct.max_bounds_width;
                                          lBearing = fontStruct.min_bounds_lbearing;
                                          rBearing = fontStruct.max_bounds_rbearing;
                                    } else {
                                          OS.memmove(charStruct, perCharPtr + (val - fontStruct.min_char_or_byte2 * XCharStruct.sizeof), XCharStruct.sizeof);
                                          charWidth = charStruct.width;
                                          lBearing = charStruct.lbearing;
                                          rBearing = charStruct.rbearing;
                                    }
                                    if (charWidth != 0) {
                                          OS.XmFontListFreeFontContext(context);
                                          return rBearing - lBearing;
                                    }
                              }
                        } else {
                              /* Double byte fontStruct */
                              int charsPerRow = fontStruct.max_char_or_byte2 - fontStruct.min_char_or_byte2 + 1;
                              int row = 0;
                              if (charBuffer.length > 1) row = charBuffer[1] - fontStruct.min_byte1;
                              int col = charBuffer[0] - fontStruct.min_char_or_byte2;
                              if (row <= fontStruct.max_byte1 && col <= fontStruct.max_char_or_byte2) {
                                    /* The font contains the character */
                                    int charWidth = 0;
                                    int lBearing = 0;
                                    int rBearing = 0;
                                    int perCharPtr = fontStruct.per_char;     
                                    if (perCharPtr == 0) {
                                          /*
                                           * If perCharPtr is 0 then all glyphs in the font have
                                           * the same width and left/right bearings as the font.
                                           */
                                          charWidth = fontStruct.max_bounds_width;
                                          lBearing = fontStruct.min_bounds_lbearing;
                                          rBearing = fontStruct.max_bounds_rbearing;
                                    } else {
                                          int offset = row * charsPerRow + col;
                                          OS.memmove(charStruct, perCharPtr + offset * XCharStruct.sizeof, XCharStruct.sizeof);
                                          charWidth = charStruct.width;
                                          lBearing = charStruct.lbearing;
                                          rBearing = charStruct.rbearing;
                                    }
                                    if (charWidth != 0) {
                                          OS.XmFontListFreeFontContext(context);
                                          return rBearing - lBearing;
                                    }
                              }
                        } 
                  }
            }
      }
      OS.XmFontListFreeFontContext(context);
      return 0;
}
/** 
 * Returns the bounding rectangle of the receiver's clipping
 * region. If no clipping region is set, the return value
 * will be a rectangle which covers the entire bounds of the
 * object the receiver is drawing on.
 *
 * @return the bounding rectangle of the clipping region
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02318 public Rectangle getClipping() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int[] width = new int[1], height = new int[1], unused = new int[1];
      OS.XGetGeometry(data.display, data.drawable, unused, unused, unused, width, height, unused, unused);
      int clipRgn = data.clipRgn;
      if (clipRgn == 0) {
            return new Rectangle(0, 0, width[0], height[0]);
      } else {
            int rgn = OS.XCreateRegion ();
            XRectangle rect = new XRectangle();
            rect.width = (short)width[0];
            rect.height = (short)height[0];
            OS.XUnionRectWithRegion(rect, rgn, rgn);
            OS.XIntersectRegion(rgn, clipRgn, rgn);
            OS.XClipBox(rgn, rect);
            OS.XDestroyRegion(rgn);
            return new Rectangle(rect.x, rect.y, rect.width, rect.height);
      }
}
/** 
 * Sets the region managed by the argument to the current
 * clipping region of the receiver.
 *
 * @param region the region to fill with the clipping region
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the region is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the region is disposed</li>
 * </ul>    
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02351 public void getClipping(Region region) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      int hRegion = region.handle;
      OS.XSubtractRegion (hRegion, hRegion, hRegion);
      int clipRgn = data.clipRgn;
      if (clipRgn == 0) {
            int[] width = new int[1], height = new int[1], unused = new int[1];
            OS.XGetGeometry(data.display, data.drawable, unused, unused, unused, width, height, unused, unused);
            XRectangle rect = new XRectangle();
            rect.x = 0;
            rect.y = 0;
            rect.width = (short)width[0];
            rect.height = (short)height[0];
            OS.XUnionRectWithRegion(rect, hRegion, hRegion);
      } else {
            OS.XUnionRegion (hRegion, clipRgn, hRegion);
            if (!isIdentity(data.matrix)) return;
      }
      if (data.damageRgn != 0) {
            OS.XIntersectRegion(hRegion, data.damageRgn, hRegion);
      }
}
String getCodePage () {
      return data.font.codePage;
}
/** 
 * Returns the receiver's fill rule, which will be one of
 * <code>SWT.FILL_EVEN_ODD</code> or <code>SWT.FILL_WINDING</code>.
 *
 * @return the receiver's fill rule
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1
 */
02389 public int getFillRule() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      XGCValues values = new XGCValues();
      OS.XGetGCValues(data.display, handle, OS.GCFillRule, values);
      return values.fill_rule == OS.WindingRule ? SWT.FILL_WINDING : SWT.FILL_EVEN_ODD;
}
/** 
 * Returns the font currently being used by the receiver
 * to draw and measure text.
 *
 * @return the receiver's font
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02405 public Font getFont () {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return Font.motif_new(data.device, data.font.handle);
}
int getFontHeight () {
      int fontList = data.font.handle;
      /* Create a font context to iterate over each element in the font list */
      int [] buffer = new int [1];
      if (!OS.XmFontListInitFontContext (buffer, fontList)) {
            SWT.error(SWT.ERROR_NO_HANDLES);
      }
      int context = buffer [0];
      
      /* Values discovering during iteration */
      int height = 0;
      XFontStruct fontStruct = new XFontStruct ();
      int fontListEntry;
      int [] fontStructPtr = new int [1];
      int [] fontNamePtr = new int [1];
      
      /* Go through each entry in the font list. */
      while ((fontListEntry = OS.XmFontListNextEntry (context)) != 0) {
            int fontPtr = OS.XmFontListEntryGetFont (fontListEntry, buffer);
            if (buffer [0] == 0) {
                  /* FontList contains a single font */
                  OS.memmove (fontStruct, fontPtr, XFontStruct.sizeof);
                  int fontHeight = fontStruct.ascent + fontStruct.descent;
                  height = Math.max(height, fontHeight);
            } else {
                  /* FontList contains a fontSet */
                  int nFonts = OS.XFontsOfFontSet (fontPtr, fontStructPtr, fontNamePtr);
                  int [] fontStructs = new int [nFonts];
                  OS.memmove (fontStructs, fontStructPtr [0], nFonts * 4);
                  
                  /* Go through each fontStruct in the font set */
                  for (int i=0; i<nFonts; i++) {
                        OS.memmove (fontStruct, fontStructs[i], XFontStruct.sizeof);
                        int fontHeight = fontStruct.ascent + fontStruct.descent;
                        height = Math.max(height, fontHeight);
                  }
            }
      }
      
      OS.XmFontListFreeFontContext (context);
      return height;
}
/**
 * Returns a FontMetrics which contains information
 * about the font currently being used by the receiver
 * to draw and measure text.
 *
 * @return font metrics for the receiver's font
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02462 public FontMetrics getFontMetrics() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int xDisplay = data.display;
      Font font = data.font;
      int fontList = font.handle;
      /* Create a font context to iterate over each element in the font list */
      int[] buffer = new int[1];
      if (!OS.XmFontListInitFontContext(buffer, fontList)) {
            SWT.error(SWT.ERROR_NO_HANDLES);
      }
      int context = buffer[0];
      /* Values discovering during iteration */
      int ascent = 0;
      int descent = 0;
      int averageCharWidth = 0, numAverageCharWidth = 0;
      int leading = 0;
      int height = 0;
            
      XFontStruct fontStruct = new XFontStruct();
      int fontListEntry;
      int[] fontStructPtr = new int[1];
      int[] fontNamePtr = new int[1];
      /* Go through each entry in the font list. */
      while ((fontListEntry = OS.XmFontListNextEntry(context)) != 0) {
            int fontPtr = OS.XmFontListEntryGetFont(fontListEntry, buffer);
            if (buffer[0] == 0) {
                  /* FontList contains a single font */
                  OS.memmove(fontStruct, fontPtr, XFontStruct.sizeof);
                  ascent = Math.max(ascent, fontStruct.ascent);
                  descent = Math.max(descent, fontStruct.descent);
                  int fontHeight = fontStruct.ascent + fontStruct.descent;
                  height = Math.max(height, fontHeight);
                  /* Calculate average character width */
                  int propPtr = fontStruct.properties;
                  for (int i = 0; i < fontStruct.n_properties; i++) {
                        /* Look through properties for XAFONT */
                        int[] prop = new int[2];
                        OS.memmove(prop, propPtr, 8);
                        if (prop[0] == OS.XA_FONT) {
                              /* Found it, prop[1] points to the string */
                              int ptr = OS.XmGetAtomName(xDisplay, prop[1]);
                              int length = OS.strlen(ptr);
                              byte[] nameBuf = new byte[length];
                              OS.memmove(nameBuf, ptr, length);
                              OS.XFree(ptr);
                              String xlfd = new String(Converter.mbcsToWcs(null, nameBuf)).toLowerCase();
                              int avg = 0;
                              try {
                                    avg = FontData.motif_new(xlfd).averageWidth / 10;
                              } catch (Exception e) {
                                    // leave avg unchanged so that it will be computed below
                              }
                              if (avg == 0) {
                                    /*
                                     * Not all fonts have average character width encoded
                                     * in the xlfd. This one doesn't, so do it the hard
                                     * way by averaging all the character widths.
                                     */                                 
                                    int perCharPtr = fontStruct.per_char;     
                                    if (perCharPtr == 0) {
                                          /*
                                           * If perCharPtr is 0 then all glyphs in the font have
                                           * the same width as the font's maximum width.  So no
                                           * averaging is required.
                                           */
                                           averageCharWidth = fontStruct.max_bounds_width;
                                    } else {
                                          int sum = 0, count = 0;
                                          int cols = fontStruct.max_char_or_byte2 - fontStruct.min_char_or_byte2 + 1;
                                          XCharStruct struct = new XCharStruct();
                                          for (int index = 0; index < cols; index++) {
                                                OS.memmove(struct, perCharPtr + (index * XCharStruct.sizeof), XCharStruct.sizeof);
                                                int w = struct.width;
                                                if (w != 0) {
                                                      sum += w;
                                                      count++;
                                                }
                                          }
                                          averageCharWidth += sum / count;
                                    }
                              } else {
                                    /* Average character width was in the xlfd */
                                    averageCharWidth += avg;
                              }
                              numAverageCharWidth++;
                              break;
                        }
                        propPtr += 8;
                  }
            } else {
                  /* FontList contains a fontSet */
                  int nFonts = OS.XFontsOfFontSet(fontPtr, fontStructPtr, fontNamePtr);
                  int [] fontStructs = new int[nFonts];
                  OS.memmove(fontStructs, fontStructPtr[0], nFonts * 4);
                  /* Go through each fontStruct in the font set */
                  for (int i = 0; i < nFonts; i++) {
                        OS.memmove(fontStruct, fontStructs[i], XFontStruct.sizeof);
                        ascent = Math.max(ascent, fontStruct.ascent);
                        descent = Math.max(descent, fontStruct.descent);
                        int fontHeight = fontStruct.ascent + fontStruct.descent;
                        height = Math.max(height, fontHeight);
                        /* Calculate average character width */
                        int propPtr = fontStruct.properties;
                        for (int j = 0; j < fontStruct.n_properties; j++) {
                              /* Look through properties for XAFONT */
                              int[] prop = new int[2];
                              OS.memmove(prop, propPtr, 8);
                              if (prop[0] == OS.XA_FONT) {
                                    /* Found it, prop[1] points to the string */
                                    int ptr = OS.XmGetAtomName(xDisplay, prop[1]);
                                    int length = OS.strlen(ptr);
                                    byte[] nameBuf = new byte[length];
                                    OS.memmove(nameBuf, ptr, length);
                                    OS.XFree(ptr);
                                    String xlfd = new String(Converter.mbcsToWcs(null, nameBuf)).toLowerCase();
                                    int avg = 0;
                                    try {
                                          avg = FontData.motif_new(xlfd).averageWidth / 10;
                                    } catch (Exception e) {
                                          /*
                                           * Some font servers, for example, xfstt, do not pass
                                           * reasonable font properties to the client, so we
                                           * cannot construct a FontData for these. Use the font
                                           * name instead.
                                           */
                                          int[] fontName = new int[1];
                                          OS.memmove(fontName, fontNamePtr [0] + (i * 4), 4);
                                          ptr = fontName[0];
                                          if (ptr != 0 ) {
                                                length = OS.strlen(ptr);
                                                nameBuf = new byte[length];
                                                OS.memmove(nameBuf, ptr, length);
                                                xlfd = new String(Converter.mbcsToWcs(null, nameBuf)).toLowerCase();
                                                try {
                                                      avg = FontData.motif_new(xlfd).averageWidth / 10;
                                                } catch (Exception ex) {
                                                      // leave avg unchanged (0) so that it will be computed below
                                                }
                                          }
                                    }
                                    if (avg == 0) {
                                          /*
                                           * Not all fonts have average character width encoded
                                           * in the xlfd. This one doesn't, so do it the hard
                                           * way by averaging all the character widths.
                                           */
                                          int perCharPtr = fontStruct.per_char;
                                          if (perCharPtr == 0) {
                                                /*
                                                 * If perCharPtr is 0 then all glyphs in the font have
                                                 * the same width as the font's maximum width.  So no
                                                 * averaging is required.
                                                 */
                                                 averageCharWidth = fontStruct.max_bounds_width;
                                          } else {
                                                int sum = 0, count = 0;
                                                int cols = fontStruct.max_char_or_byte2 - fontStruct.min_char_or_byte2 + 1;
                                                XCharStruct struct = new XCharStruct();
                                                for (int index = 0; index < cols; index++) {
                                                      OS.memmove(struct, perCharPtr + (index * XCharStruct.sizeof), XCharStruct.sizeof);
                                                      int w = struct.width;
                                                      if (w != 0) {
                                                            sum += w;
                                                            count++;
                                                      }
                                                }
                                                averageCharWidth += sum / count;
                                          }
                                    } else {
                                          /* Average character width was in the xlfd */
                                          averageCharWidth += avg;
                                    }
                                    numAverageCharWidth++;
                                    break;
                              }
                              propPtr += 8;
                        }
                  }
            }
      }
      OS.XmFontListFreeFontContext(context);
      return FontMetrics.motif_new(ascent, descent, averageCharWidth / numAverageCharWidth, leading, height);
}
/** 
 * Returns the receiver's foreground color.
 *
 * @return the color used for drawing foreground things
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02654 public Color getForeground() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int xDisplay = data.display;
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCForeground, values);
      XColor xColor = new XColor();
      xColor.pixel = values.foreground;
      OS.XQueryColor(xDisplay,data.colormap,xColor);
      return Color.motif_new(data.device, xColor);
      
}
/** 
 * Returns the foreground pattern. The default value is
 * <code>null</code>.
 *
 * @return the receiver's foreground pattern
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Pattern
 * 
 * @since 3.1
 */
02679 public Pattern getForegroundPattern() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return data.foregroundPattern;
}
/** 
 * Returns the receiver's interpolation setting, which will be one of
 * <code>SWT.DEFAULT</code>, <code>SWT.NONE</code>, 
 * <code>SWT.LOW</code> or <code>SWT.HIGH</code>.
 *
 * @return the receiver's interpolation setting
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1
 */
02696 public int getInterpolation() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return data.interpolation;
}
/** 
 * Returns the receiver's line cap style, which will be one
 * of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
 * or <code>SWT.CAP_SQUARE</code>.
 *
 * @return the cap style used for drawing lines
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1 
 */
02713 public int getLineCap() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      XGCValues values = new XGCValues();
      OS.XGetGCValues(data.display, handle, OS.GCCapStyle, values);
      int cap = SWT.CAP_FLAT;
      switch (values.cap_style) {
            case OS.CapRound: cap = SWT.CAP_ROUND; break;
            case OS.CapButt: cap = SWT.CAP_FLAT; break;
            case OS.CapProjecting: cap = SWT.CAP_SQUARE; break;
      }
      return cap;
}
/** 
 * Returns the receiver's line dash style. The default value is
 * <code>null</code>.
 *
 * @return the lin dash style used for drawing lines
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1 
 */
02737 public int[] getLineDash() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int[] dash_list = data.dashes;
      if (dash_list == null) return null;
      int[] dashes = new int[dash_list.length];
      System.arraycopy(dash_list, 0, dashes, 0, dashes.length);
      return dashes;
}
/** 
 * Returns the receiver's line join style, which will be one
 * of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
 * or <code>SWT.JOIN_BEVEL</code>.
 *
 * @return the join style used for drawing lines
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1 
 */
02758 public int getLineJoin() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      XGCValues values = new XGCValues();
      OS.XGetGCValues(data.display, handle, OS.GCJoinStyle, values);
      int join = SWT.JOIN_MITER;
      switch (values.join_style) {
            case OS.JoinMiter: join = SWT.JOIN_MITER; break;
            case OS.JoinRound: join = SWT.JOIN_ROUND; break;
            case OS.JoinBevel: join = SWT.JOIN_BEVEL; break;
      }
      return join;
}
/** 
 * Returns the receiver's line style, which will be one
 * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
 * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
 * <code>SWT.LINE_DASHDOTDOT</code>.
 *
 * @return the style used for drawing lines
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02782 public int getLineStyle() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return data.lineStyle;
}
/** 
 * Returns the width that will be used when drawing lines
 * for all of the figure drawing operations (that is,
 * <code>drawLine</code>, <code>drawRectangle</code>, 
 * <code>drawPolyline</code>, and so forth.
 *
 * @return the receiver's line width 
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02798 public int getLineWidth() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      XGCValues values = new XGCValues();
      OS.XGetGCValues(data.display, handle, OS.GCLineWidth, values);
      return values.line_width;
}
/**
 * Returns the receiver's style information.
 * <p>
 * Note that the value which is returned by this method <em>may
 * not match</em> the value which was provided to the constructor
 * when the receiver was created. This can occur when the underlying
 * operating system does not support a particular combination of
 * requested styles. 
 * </p>
 *
 * @return the style bits
 *  
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *   
 * @since 2.1.2
 */
02822 public int getStyle () {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return data.style;
}
/**
 * Returns the receiver's text drawing anti-aliasing setting value,
 * which will be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code> or
 * <code>SWT.ON</code>. Note that this controls anti-aliasing
 * <em>only</em> for text drawing operations.
 *
 * @return the anti-aliasing setting
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see #getAntialias
 * 
 * @since 3.1
 */
02842 public int getTextAntialias() {
    if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
    return data.textAntialias;
}
/** 
 * Sets the parameter to the transform that is currently being
 * used by the receiver.
 *
 * @param transform the destination to copy the transform into
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Transform
 * 
 * @since 3.1
 */
02864 public void getTransform(Transform transform) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (transform == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_matrix_copy(transform.handle, data.matrix);
      } else {
            transform.setElements(1, 0, 0, 1, 0, 0);
      }
}
/** 
 * Returns <code>true</code> if this GC is drawing in the mode
 * where the resulting color in the destination is the
 * <em>exclusive or</em> of the color values in the source
 * and the destination, and <code>false</code> if it is
 * drawing in the mode where the destination color is being
 * replaced with the source color value.
 *
 * @return <code>true</code> true if the receiver is in XOR mode, and false otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02889 public boolean getXORMode() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      XGCValues values = new XGCValues ();
      OS.XGetGCValues (data.display, handle, OS.GCFunction, values);
      return values.function == OS.GXxor;
}
/**
 * Returns an integer hash code for the receiver. Any two 
 * objects that return <code>true</code> when passed to 
 * <code>equals</code> must return the same value for this
 * method.
 *
 * @return the receiver's hash
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 *
 * @see #equals
 */
02909 public int hashCode () {
      return handle;
}
void init(Drawable drawable, GCData data, int xGC) {
      int xDisplay = data.display;
      int foreground = data.foreground;
      if (foreground != -1) OS.XSetForeground (xDisplay, xGC, foreground);
      int background = data.background;
      if (background != -1) OS.XSetBackground (xDisplay, xGC, background);
      Image image = data.image;
      if (image != null) {
            image.memGC = this;
            /*
             * The transparent pixel mask might change when drawing on
             * the image.  Destroy it so that it is regenerated when
             * necessary.
             */
            if (image.transparentPixel != -1) image.destroyMask();
      }
      this.drawable = drawable;
      this.data = data;
      handle = xGC;
}
void initCairo() {
      data.device.checkCairo();
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) return;
      data.cairo = cairo = Cairo.cairo_create();
      if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES);
      data.matrix = Cairo.cairo_matrix_create();
      if (data.matrix == 0) SWT.error(SWT.ERROR_NO_HANDLES);
      data.inverseMatrix = Cairo.cairo_matrix_create();
      if (data.inverseMatrix == 0) SWT.error(SWT.ERROR_NO_HANDLES);
      int /*long*/ xDisplay = data.display;
      int /*long*/ xDrawable = data.drawable;
      Cairo.cairo_set_target_drawable(cairo, xDisplay, xDrawable);
      Cairo.cairo_set_fill_rule(cairo, Cairo.CAIRO_FILL_RULE_EVEN_ODD);
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCBackground | OS.GCCapStyle | OS.GCForeground | OS.GCJoinStyle | OS.GCLineWidth, values);
      XColor color = new XColor();
      color.pixel = values.foreground;
      OS.XQueryColor(xDisplay, data.colormap, color);
      Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
      Cairo.cairo_set_line_width(cairo, Math.max(1, values.line_width));
      int cap = Cairo.CAIRO_LINE_CAP_BUTT;
      switch (values.cap_style) {
            case OS.CapRound: cap = Cairo.CAIRO_LINE_CAP_ROUND; break;
            case OS.CapButt: cap = Cairo.CAIRO_LINE_CAP_BUTT; break;
            case OS.CapProjecting: cap = Cairo.CAIRO_LINE_CAP_SQUARE; break;
      }
      Cairo.cairo_set_line_cap(cairo, cap);
      int join = Cairo.CAIRO_LINE_JOIN_MITER;
      switch (values.join_style) {
            case OS.JoinMiter: join = Cairo.CAIRO_LINE_JOIN_MITER; break;
            case OS.JoinRound: join = Cairo.CAIRO_LINE_JOIN_ROUND; break;
            case OS.JoinBevel: join = Cairo.CAIRO_LINE_JOIN_BEVEL; break;
      }
      Cairo.cairo_set_line_join(cairo, join);
      if (data.dashes != null) {
            double[] dashes = new double[data.dashes.length];
            for (int i = 0; i < dashes.length; i++) {
                  dashes[i] = data.dashes[i];
            }
            Cairo.cairo_set_dash(cairo, dashes, dashes.length, 0);
      }
      setCairoFont(cairo, data.font);
      setCairoClip(cairo, data.clipRgn);
}
/**
 * Returns <code>true</code> if the receiver has a clipping
 * region set into it, and <code>false</code> otherwise.
 * If this method returns false, the receiver will draw on all
 * available space in the destination. If it returns true, 
 * it will draw only in the area that is covered by the region
 * that can be accessed with <code>getClipping(region)</code>.
 *
 * @return <code>true</code> if the GC has a clipping region, and <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
02991 public boolean isClipped() {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      return data.clipRgn != 0;
}
/**
 * Returns <code>true</code> if the GC has been disposed,
 * and <code>false</code> otherwise.
 * <p>
 * This method gets the dispose state for the GC.
 * When a GC has been disposed, it is an error to
 * invoke any other method using the GC.
 *
 * @return <code>true</code> when the GC is disposed and <code>false</code> otherwise
 */
03005 public boolean isDisposed() {
      return handle == 0;
}
boolean isIdentity(int /*long*/ matrix) {
      if (matrix == 0) return true;
      double[] a = new double[1], b = new double[1], c = new double[1];
      double[] d = new double[1], tx = new double[1], ty = new double[1];                 
      Cairo.cairo_matrix_get_affine(matrix, a, b, c, d, tx, ty);
      return a[0] == 1 && b[0] == 0 && c[0] == 0 && d[0] == 1 && tx[0] == 0 && ty[0] == 0;
}
/**
 * Sets the receiver to always use the operating system's advanced graphics
 * subsystem for all graphics operations if the argument is <code>true</code>.
 * If the argument is <code>false</code>, the advanced graphics subsystem is 
 * no longer used, advanced graphics state is cleared and the normal graphics
 * subsystem is used from now on.
 * <p>
 * Normally, the advanced graphics subsystem is invoked automatically when
 * any one of the alpha, antialias, patterns, interpolation, paths, clipping
 * or transformation operations in the receiver is requested.  When the receiver
 * is switched into advanced mode, the advanced graphics subsystem performs both
 * advanced and normal graphics operations.  Because the two subsystems are
 * different, their output may differ.  Switching to advanced graphics before
 * any graphics operations are performed ensures that the output is consistent.
 * </p>
 * <p>
 * Advanced graphics may not be installed for the operating system.  In this
 * case, this operation does nothing.  Some operating system have only one
 * graphics subsystem, so switching from normal to advanced graphics does
 * nothing.  However, switching from advanced to normal graphics will always
 * clear the advanced graphics state, even for operating systems that have
 * only one graphics subsystem.
 * </p>
 *
 * @param advanced the new advanced graphics state
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see #setAlpha
 * @see #setAntialias
 * @see #setBackgroundPattern
 * @see #setClipping(Path)
 * @see #setForegroundPattern
 * @see #setInterpolation
 * @see #setTextAntialias
 * @see #setTransform
 * @see #getAdvanced
 * 
 * @since 3.1
 */
03057 public void setAdvanced(boolean advanced) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (advanced && data.cairo != 0) return;
      if (advanced) {
            try {
                  initCairo();
            } catch (SWTException e) {}
      } else {
            int /*long*/ cairo = data.cairo;
            if (cairo != 0) Cairo.cairo_destroy(cairo);
            int /*long*/ matrix = data.matrix;
            if (matrix != 0) Cairo.cairo_matrix_destroy(matrix);
            int /*long*/ inverseMatrix = data.inverseMatrix;
            if (inverseMatrix != 0) Cairo.cairo_matrix_destroy(inverseMatrix);
            data.cairo = data.matrix = data.inverseMatrix = 0;
            data.antialias = data.textAntialias = data.interpolation = SWT.DEFAULT;
            data.backgroundPattern = data.foregroundPattern = null;
            setClipping(0);
      }
}
/**
 * Sets the receiver's alpha value.
 *
 * @param alpha the alpha value
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1
 */
03088 public void setAlpha(int alpha) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (data.cairo == 0 && (alpha & 0xff) == 0xff) return;
      initCairo();
      Cairo.cairo_set_alpha(data.cairo, (alpha & 0xff) / 255f);
}
/**
 * Sets the receiver's anti-aliasing value to the parameter, 
 * which must be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code>
 * or <code>SWT.ON</code>. Note that this controls anti-aliasing for all
 * <em>non-text drawing</em> operations.
 *
 * @param antialias the anti-aliasing setting
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter is not one of <code>SWT.DEFAULT</code>,
 *                                 <code>SWT.OFF</code> or <code>SWT.ON</code></li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see #setTextAntialias
 * 
 * @since 3.1
 */
03114 public void setAntialias(int antialias) {
    if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (data.cairo == 0 && antialias == SWT.DEFAULT) return;
    switch (antialias) {
        case SWT.DEFAULT: break;
        case SWT.OFF: break;
        case SWT.ON:
            initCairo();
            break;
        default:
            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
    }
    data.antialias = antialias;
}
/**    
 * Invokes platform specific functionality to allocate a new graphics context.
 * <p>
 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
 * API for <code>GC</code>. It is marked public only so that it
 * can be shared within the packages provided by SWT. It is not
 * available on all platforms, and should never be called from
 * application code.
 * </p>
 *
 * @param drawable the Drawable for the receiver.
 * @param data the data for the receiver.
 *
 * @return a new <code>GC</code>
 */
03143 public static GC motif_new(Drawable drawable, GCData data) {
      GC gc = new GC();
      int xGC = drawable.internal_new_GC(data);
      gc.init(drawable, data, xGC);
      return gc;
}
/**    
 * Invokes platform specific functionality to wrap a graphics context.
 * <p>
 * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
 * API for <code>GC</code>. It is marked public only so that it
 * can be shared within the packages provided by SWT. It is not
 * available on all platforms, and should never be called from
 * application code.
 * </p>
 *
 * @param xGC the X Windows graphics context.
 * @param data the data for the receiver.
 *
 * @return a new <code>GC</code>
 */
03164 public static GC motif_new(int xGC, GCData data) {
      GC gc = new GC();
      gc.init(null, data, xGC);
      return gc;
}
/**
 * Sets the background color. The background color is used
 * for fill operations and as the background color when text
 * is drawn.
 *
 * @param color the new background color for the receiver
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the color is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03184 public void setBackground (Color color) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      OS.XSetBackground(data.display, handle, color.handle.pixel);
      data.backgroundPattern = null;
}
/** 
 * Sets the background pattern. The default value is <code>null</code>.
 *
 * @param pattern the new background pattern
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Pattern
 * 
 * @since 3.1
 */
03207 public void setBackgroundPattern(Pattern pattern) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      if (data.cairo == 0 && pattern == null) return;
      initCairo();
      data.backgroundPattern = pattern;
}
static void setCairoFont(int /*long*/ cairo, Font font) {
      //TODO - use X font instead of loading new one???
      FontData[] fds = font.getFontData();
      FontData fd = fds[0];
      int style = fd.getStyle();
      int slant = Cairo.CAIRO_FONT_SLANT_NORMAL;
      if ((style & SWT.ITALIC) != 0) slant = Cairo.CAIRO_FONT_SLANT_ITALIC;
      int weight = Cairo.CAIRO_FONT_WEIGHT_NORMAL;
      if ((style & SWT.BOLD) != 0) weight = Cairo.CAIRO_FONT_WEIGHT_BOLD;
      byte[] buffer = Converter.wcsToMbcs(null, fd.getName(), true);
      Cairo.cairo_select_font(cairo, buffer, slant, weight);
      Cairo.cairo_scale_font(cairo, fd.getHeight());
}
static void setCairoClip(int /*long*/ cairo, int /*long*/ clipRgn) {
      Cairo.cairo_init_clip(cairo);
      if (clipRgn == 0) return;
      //TODO - get rectangles from region instead of clip box
      XRectangle rect = new XRectangle();
      OS.XClipBox(clipRgn, rect);
      Cairo.cairo_rectangle(cairo, rect.x, rect.y, rect.width, rect.height);
      Cairo.cairo_clip(cairo);
      Cairo.cairo_new_path(cairo);
}
static void setCairoPatternColor(int /*long*/ pattern, int offset, Color c) {
      XColor color = c.handle;
      Cairo.cairo_pattern_add_color_stop(pattern, offset, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF, 1);
}
void setClipping(int clipRgn) {
      if (clipRgn == 0) {
            if (data.clipRgn != 0) {
                  OS.XDestroyRegion (data.clipRgn);
                  data.clipRgn = 0;
            } else {
                  return;
            }
            if (data.damageRgn == 0) {
                  OS.XSetClipMask (data.display, handle, OS.None);
            } else {
                  OS.XSetRegion (data.display, handle, data.damageRgn);             
            }
      } else {
            if (data.clipRgn == 0) data.clipRgn = OS.XCreateRegion ();
            OS.XSubtractRegion (data.clipRgn, data.clipRgn, data.clipRgn);
            OS.XUnionRegion (clipRgn, data.clipRgn, data.clipRgn);
            int clipping = clipRgn;
            if (data.damageRgn != 0) {
                  clipping = OS.XCreateRegion();
                  OS.XUnionRegion(clipping, clipRgn, clipping);
                  OS.XIntersectRegion(clipping, data.damageRgn, clipping);
            }
            OS.XSetRegion (data.display, handle, clipping);
            if (clipping != clipRgn) OS.XDestroyRegion(clipping);
      }
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            setCairoClip(cairo, clipRgn);
      }
}
/**
 * Sets the area of the receiver which can be changed
 * by drawing operations to the rectangular area specified
 * by the arguments.
 *
 * @param x the x coordinate of the clipping rectangle
 * @param y the y coordinate of the clipping rectangle
 * @param width the width of the clipping rectangle
 * @param height the height of the clipping rectangle
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03286 public void setClipping (int x, int y, int width, int height) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (width < 0) {
            x = x + width;
            width = -width;
      }
      if (height < 0) {
            y = y + height;
            height = -height;
      }
      XRectangle rect = new XRectangle ();
      rect.x = (short) x; 
      rect.y = (short) y;
      rect.width = (short) Math.max (0, width); 
      rect.height = (short) Math.max (0, height);
      int clipRgn = OS.XCreateRegion();
      OS.XUnionRectWithRegion(rect, clipRgn, clipRgn);
      setClipping(clipRgn);
      OS.XDestroyRegion(clipRgn);
}
/**
 * Sets the area of the receiver which can be changed
 * by drawing operations to the path specified
 * by the argument.
 *
 * @param path the clipping path.
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the path has been disposed</li>
 * </ul> 
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Path
 * 
 * @since 3.1
 */
03324 public void setClipping(Path path) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (path != null && path.isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      setClipping(0);
      if (path != null) {
            initCairo();
            int /*long*/ cairo = data.cairo;
            Cairo.cairo_add_path(cairo, path.handle);
            Cairo.cairo_clip(cairo);
            Cairo.cairo_new_path(cairo);
      }
}
/**
 * Sets the area of the receiver which can be changed
 * by drawing operations to the rectangular area specified
 * by the argument.  Specifying <code>null</code> for the
 * rectangle reverts the receiver's clipping area to its
 * original value.
 *
 * @param rect the clipping rectangle or <code>null</code>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03349 public void setClipping (Rectangle rect) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (rect == null) {
            setClipping(0);
      } else {
            setClipping (rect.x, rect.y, rect.width, rect.height);
      }
}
/**
 * Sets the area of the receiver which can be changed
 * by drawing operations to the region specified
 * by the argument.  Specifying <code>null</code> for the
 * region reverts the receiver's clipping area to its
 * original value.
 *
 * @param region the clipping region or <code>null</code>
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the region has been disposed</li>
 * </ul> 
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03373 public void setClipping (Region region) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (region != null && region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      setClipping(region != null ? region.handle : 0);
}
/** 
 * Sets the receiver's fill rule to the parameter, which must be one of
 * <code>SWT.FILL_EVEN_ODD</code> or <code>SWT.FILL_WINDING</code>.
 *
 * @param rule the new fill rule
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the rule is not one of <code>SWT.FILL_EVEN_ODD</code>
 *                                 or <code>SWT.FILL_WINDING</code></li>
 * </ul> 
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1
 */
03394 public void setFillRule(int rule) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int mode = OS.EvenOddRule, cairo_mode = Cairo.CAIRO_FILL_RULE_EVEN_ODD;
      switch (rule) {
            case SWT.FILL_WINDING:
                  mode = OS.WindingRule; cairo_mode = Cairo.CAIRO_FILL_RULE_WINDING; break;
            case SWT.FILL_EVEN_ODD:
                  mode = OS.EvenOddRule; cairo_mode = Cairo.CAIRO_FILL_RULE_EVEN_ODD; break;
            default:
                  SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      }
      OS.XSetFillRule(data.display, handle, mode);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_set_fill_rule(cairo, cairo_mode);
      }
}
/** 
 * Sets the font which will be used by the receiver
 * to draw and measure text to the argument. If the
 * argument is null, then a default font appropriate
 * for the platform will be used instead.
 *
 * @param font the new font for the receiver, or null to indicate a default font
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03426 public void setFont (Font font) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (font == null) font = data.device.systemFont;
      if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      data.font = font;
      if (data.renderTable != 0) OS.XmRenderTableFree(data.renderTable);
      data.renderTable = 0;
      data.stringWidth = data.stringHeight = data.textWidth = data.textHeight = -1;
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            setCairoFont(cairo, font);
      }
}
/**
 * Sets the foreground color. The foreground color is used
 * for drawing operations including when text is drawn.
 *
 * @param color the new foreground color for the receiver
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the color is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03453 public void setForeground (Color color) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      OS.XSetForeground(data.display, handle, color.handle.pixel);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            XColor xColor = color.handle;
            Cairo.cairo_set_rgb_color(cairo, (xColor.red & 0xFFFF) / (float)0xFFFF, (xColor.green & 0xFFFF) / (float)0xFFFF, (xColor.blue & 0xFFFF) / (float)0xFFFF);
      }
      data.foregroundPattern = null;
}
/** 
 * Sets the foreground pattern. The default value is <code>null</code>.
 *
 * @param pattern the new foreground pattern
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Pattern
 * 
 * @since 3.1
 */
03481 public void setForegroundPattern(Pattern pattern) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (pattern != null && pattern.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      if (data.cairo == 0 && pattern == null) return;
      initCairo();
      int /*long*/ cairo = data.cairo;
      if (pattern != null) {
            Cairo.cairo_set_pattern(cairo, pattern.handle);
      } else {
            int display = data.display;
            XGCValues values = new XGCValues ();
            OS.XGetGCValues (display, handle, OS.GCForeground, values);
            XColor color = new XColor();
            color.pixel = values.foreground;
            OS.XQueryColor(display, data.colormap, color);
            Cairo.cairo_set_rgb_color(cairo, (color.red & 0xFFFF) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF);
      }
      data.foregroundPattern = pattern;
}
/** 
 * Sets the receiver's interpolation setting to the parameter, which
 * must be one of <code>SWT.DEFAULT</code>, <code>SWT.NONE</code>, 
 * <code>SWT.LOW</code> or <code>SWT.HIGH</code>.
 *
 * @param interpolation the new interpolation setting
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the rule is not one of <code>SWT.DEFAULT</code>, 
 *                                 <code>SWT.NONE</code>, <code>SWT.LOW</code> or <code>SWT.HIGH</code>
 * </ul> 
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1
 */
03517 public void setInterpolation(int interpolation) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (data.cairo == 0 && interpolation == SWT.DEFAULT) return;
      switch (interpolation) {
            case SWT.DEFAULT:
            case SWT.NONE:
            case SWT.LOW:
            case SWT.HIGH:
                  break;
            default:
                  SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      }
      initCairo();
      data.interpolation = interpolation;
}
/** 
 * Sets the receiver's line cap style to the argument, which must be one
 * of the constants <code>SWT.CAP_FLAT</code>, <code>SWT.CAP_ROUND</code>,
 * or <code>SWT.CAP_SQUARE</code>.
 *
 * @param cap the cap style to be used for drawing lines
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
 * </ul> 
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1 
 */
03548 public void setLineCap(int cap) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int cap_style = 0, cairo_style = 0;
      switch (cap) {
            case SWT.CAP_ROUND:
                  cap_style = OS.CapRound;
                  cairo_style = Cairo.CAIRO_LINE_CAP_ROUND;
                  break;
            case SWT.CAP_FLAT:
                  cap_style = OS.CapButt;
                  cairo_style = Cairo.CAIRO_LINE_CAP_BUTT;
                  break;
            case SWT.CAP_SQUARE:
                  cap_style = OS.CapProjecting;
                  cairo_style = Cairo.CAIRO_LINE_CAP_SQUARE;
                  break;
            default:
                  SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      }
      int xDisplay = data.display;
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCLineWidth | OS.GCJoinStyle, values);
      int line_style = data.lineStyle == SWT.LINE_SOLID ? OS.LineSolid : OS.LineOnOffDash;
      OS.XSetLineAttributes(xDisplay, handle, values.line_width, line_style, cap_style, values.join_style);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_set_line_cap(cairo, cairo_style);
      }
}
/** 
 * Sets the receiver's line dash style to the argument. The default
 * value is <code>null</code>. If the argument is not <code>null</code>,
 * the receiver's line style is set to <code>SWT.LINE_CUSTOM</code>, otherwise
 * it is set to <code>SWT.LINE_SOLID</code>.
 *
 * @param dashes the dash style to be used for drawing lines
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if any of the values in the array is less than or equal 0</li>
 * </ul> 
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1 
 */
03594 public void setLineDash(int[] dashes) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int xDisplay = data.display;
      if (dashes != null && dashes.length != 0) {
            byte[] dash_list = new byte[dashes.length];
            for (int i = 0; i < dashes.length; i++) {
                  int dash = dashes[i];
                  if (dash <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
                  dash_list[i] = (byte)dash;
            }
            OS.XSetDashes(xDisplay, handle, 0, dash_list, dash_list.length);
            data.dashes = new int[dashes.length];
            System.arraycopy(dashes, 0, data.dashes, 0, dashes.length);
            data.lineStyle = SWT.LINE_CUSTOM;
      } else {
            data.dashes = null;
            data.lineStyle = SWT.LINE_SOLID;
      }
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCLineWidth | OS.GCCapStyle | OS.GCJoinStyle, values);
      int line_style = data.lineStyle == SWT.LINE_SOLID ? OS.LineSolid : OS.LineOnOffDash;
      OS.XSetLineAttributes(xDisplay, handle, values.line_width, line_style, values.cap_style, values.join_style);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            if (data.dashes != null) {
                  double[] cairoDashes = new double[data.dashes.length];
                  for (int i = 0; i < dashes.length; i++) {
                        cairoDashes[i] = data.dashes[i];
                  }
                  Cairo.cairo_set_dash(cairo, cairoDashes, cairoDashes.length, 0);
            } else {
                  Cairo.cairo_set_dash(cairo, null, 0, 0);
            }
      }
}
/** 
 * Sets the receiver's line join style to the argument, which must be one
 * of the constants <code>SWT.JOIN_MITER</code>, <code>SWT.JOIN_ROUND</code>,
 * or <code>SWT.JOIN_BEVEL</code>.
 *
 * @param join the join style to be used for drawing lines
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @since 3.1 
 */
03645 public void setLineJoin(int join) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int join_style = 0, cairo_style = 0;
      switch (join) {
            case SWT.JOIN_MITER:
                  join_style = OS.JoinMiter;
                  cairo_style = Cairo.CAIRO_LINE_JOIN_MITER;
                  break;
            case SWT.JOIN_ROUND:
                  join_style = OS.JoinRound;
                  cairo_style = Cairo.CAIRO_LINE_JOIN_ROUND;
                  break;
            case SWT.JOIN_BEVEL:
                  join_style = OS.JoinBevel;
                  cairo_style = Cairo.CAIRO_LINE_JOIN_BEVEL;
                  break;
            default:
                  SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      }
      int xDisplay = data.display;
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCLineWidth | OS.GCCapStyle, values);
      int line_style = data.lineStyle == SWT.LINE_SOLID ? OS.LineSolid : OS.LineOnOffDash;
      OS.XSetLineAttributes(xDisplay, handle, values.line_width, line_style, values.cap_style, join_style);
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_set_line_join(cairo, cairo_style);
      }
}
/** 
 * Sets the receiver's line style to the argument, which must be one
 * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
 * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
 * <code>SWT.LINE_DASHDOTDOT</code>.
 *
 * @param lineStyle the style to be used for drawing lines
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the style is not valid</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03689 public void setLineStyle(int lineStyle) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int xDisplay = data.display;
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCLineWidth | OS.GCCapStyle | OS.GCJoinStyle, values);
      int[] dashes = null;
      int width = values.line_width;
      switch (lineStyle) {
            case SWT.LINE_SOLID:
                  break;
            case SWT.LINE_DASH:
                  dashes = width != 0 ? LINE_DASH : LINE_DASH_ZERO;
                  break;
            case SWT.LINE_DOT:
                  dashes = width != 0 ? LINE_DOT : LINE_DOT_ZERO;
                  break;
            case SWT.LINE_DASHDOT:
                  dashes = width != 0 ? LINE_DASHDOT : LINE_DASHDOT_ZERO;
                  break;
            case SWT.LINE_DASHDOTDOT:
                  dashes = width != 0 ? LINE_DASHDOTDOT : LINE_DASHDOTDOT_ZERO;
                  break;
            case SWT.LINE_CUSTOM:
                  dashes = data.dashes;
                  if (dashes == null) lineStyle = SWT.LINE_SOLID;
                  break;
            default:
                  SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      }
      data.lineStyle = lineStyle;
      OS.XSetLineAttributes(xDisplay, handle, values.line_width, dashes != null ? OS.LineOnOffDash : OS.LineSolid, values.cap_style, values.join_style);
      if (dashes != null) {
            byte[] dash_list = new byte[dashes.length];
            for (int i = 0; i < dash_list.length; i++) {
                  dash_list[i] = (byte)(width == 0 ? dashes[i] : dashes[i] * width);
            }
            OS.XSetDashes(xDisplay, handle, 0, dash_list, dash_list.length);
      }
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            if (dashes != null) {
                  double[] cairoDashes = new double[dashes.length];
                  for (int i = 0; i < cairoDashes.length; i++) {
                        cairoDashes[i] = width == 0 ? dashes[i] : dashes[i] * width;
                  }
                  Cairo.cairo_set_dash(cairo, cairoDashes, cairoDashes.length, 0);
            } else {
                  Cairo.cairo_set_dash(cairo, null, 0, 0);
            }
      }
}
/** 
 * Sets the width that will be used when drawing lines
 * for all of the figure drawing operations (that is,
 * <code>drawLine</code>, <code>drawRectangle</code>, 
 * <code>drawPolyline</code>, and so forth.
 * <p>
 * Note that line width of zero is used as a hint to
 * indicate that the fastest possible line drawing
 * algorithms should be used. This means that the
 * output may be different from line width one.
 * </p>
 *
 * @param lineWidth the width of a line
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03758 public void setLineWidth(int lineWidth) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      int xDisplay = data.display;
      XGCValues values = new XGCValues();
      OS.XGetGCValues(xDisplay, handle, OS.GCLineWidth | OS.GCCapStyle | OS.GCJoinStyle, values);
      int line_style = data.lineStyle == SWT.LINE_SOLID ? OS.LineSolid : OS.LineOnOffDash;
      OS.XSetLineAttributes(data.display, handle, lineWidth, line_style, values.cap_style, values.join_style);
      data.lineWidth = lineWidth;
      int /*long*/ cairo = data.cairo;
      if (cairo != 0) {
            Cairo.cairo_set_line_width(cairo, Math.max(1, lineWidth));
      }
      switch (data.lineStyle) {
            case SWT.LINE_DOT:
            case SWT.LINE_DASH:
            case SWT.LINE_DASHDOT:
            case SWT.LINE_DASHDOTDOT:
                  setLineStyle(data.lineStyle);
      }
}
void setString(String string) {
      if (string == data.string) return;
      if (data.xmString != 0) OS.XmStringFree(data.xmString);
      byte[] buffer = Converter.wcsToMbcs(getCodePage (), string, true);
      data.xmString = OS.XmStringCreate(buffer, OS.XmFONTLIST_DEFAULT_TAG);
      data.string = string;
      data.stringWidth = data.stringHeight = -1;
}
void setText(String string, int flags) {
      if (data.renderTable == 0) createRenderTable();
      if (string == data.text && (flags & ~SWT.DRAW_TRANSPARENT) == (data.drawFlags & ~SWT.DRAW_TRANSPARENT)) {
            return;
      }
      if (data.xmText != 0) OS.XmStringFree(data.xmText);
      if (data.xmMnemonic != 0) OS.XmStringFree(data.xmMnemonic);
      char mnemonic = 0;
      int tableLength = 0;
      Device device = data.device;
      int[] parseTable = new int[2];
      char[] text = new char[string.length()];
      string.getChars(0, text.length, text, 0); 
      if ((flags & SWT.DRAW_DELIMITER) != 0) parseTable[tableLength++] = device.crMapping;
      if ((flags & SWT.DRAW_TAB) != 0) parseTable[tableLength++] = device.tabMapping;
      if ((flags & SWT.DRAW_MNEMONIC) != 0) mnemonic = fixMnemonic(text);
      String codePage = getCodePage();
      byte[] buffer = Converter.wcsToMbcs(codePage, text, true);
      data.xmText = OS.XmStringParseText(buffer, 0, OS.XmFONTLIST_DEFAULT_TAG, OS.XmCHARSET_TEXT, parseTable, tableLength, 0);
      if (mnemonic != 0) {
            byte [] buffer1 = Converter.wcsToMbcs(codePage, new char[]{mnemonic}, true);
            data.xmMnemonic = OS.XmStringCreate (buffer1, OS.XmFONTLIST_DEFAULT_TAG);
      } else {
            data.xmMnemonic = 0;
      }
      data.text = string;
      data.textWidth = data.textHeight = -1;
      data.drawFlags = flags;
}
/**
 * Sets the receiver's text anti-aliasing value to the parameter, 
 * which must be one of <code>SWT.DEFAULT</code>, <code>SWT.OFF</code>
 * or <code>SWT.ON</code>. Note that this controls anti-aliasing only
 * for all <em>text drawing</em> operations.
 *
 * @param antialias the anti-aliasing setting
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter is not one of <code>SWT.DEFAULT</code>,
 *                                 <code>SWT.OFF</code> or <code>SWT.ON</code></li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see #setAntialias
 * 
 * @since 3.1
 */
03835 public void setTextAntialias(int antialias) {
    if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (data.cairo == 0 && antialias == SWT.DEFAULT) return;
    switch (antialias) {
        case SWT.DEFAULT: break;
        case SWT.OFF: break;
        case SWT.ON: break;
        default:
            SWT.error(SWT.ERROR_INVALID_ARGUMENT);
    }
    data.textAntialias = antialias;
}
/** 
 * Sets the transform that is currently being used by the receiver. If
 * the argument is <code>null</code>, the current transform is set to
 * the identity transform.
 *
 * @param transform the transform to set
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_INVALID_ARGUMENT - if the parameter has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @see Transform
 * 
 * @since 3.1
 */
03865 public void setTransform(Transform transform) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (transform != null && transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
      if (data.cairo == 0 && transform == null) return;
      initCairo();
      int /*long*/ cairo = data.cairo;
      Cairo.cairo_concat_matrix(cairo, data.inverseMatrix);
      if (transform != null) {
            Cairo.cairo_concat_matrix(cairo, transform.handle);
            Cairo.cairo_matrix_copy(data.matrix, transform.handle);
            Cairo.cairo_matrix_copy(data.inverseMatrix, transform.handle);
            Cairo.cairo_matrix_invert(data.inverseMatrix);
      } else {
            Cairo.cairo_matrix_set_identity(data.matrix);
            Cairo.cairo_matrix_set_identity(data.inverseMatrix);
      }
      //TODO - round off problems
      int /*long*/ clipRgn = data.clipRgn;
      if (clipRgn != 0) {
            int /*long*/ matrix = data.inverseMatrix;
            int /*long*/ newRgn = OS.XCreateRegion();
            //TODO - get rectangles from region instead of clip box
            XRectangle rect = new XRectangle();
            OS.XClipBox(clipRgn, rect);
            short[] pointArray = new short[8];
            double[] x = new double[1], y = new double[1];
            x[0] = rect.x;
            y[0] = rect.y;
            Cairo.cairo_matrix_transform_point(matrix, x, y);
            pointArray[0] = (short)Math.round(x[0]);
            pointArray[1] = (short)Math.round(y[0]);
            x[0] = rect.x + rect.width;
            y[0] = rect.y;
            Cairo.cairo_matrix_transform_point(matrix, x, y);
            pointArray[2] = (short)Math.round(x[0]);
            pointArray[3] = (short)Math.round(y[0]);
            x[0] = rect.x + rect.width;
            y[0] = rect.y + rect.height;
            Cairo.cairo_matrix_transform_point(matrix, x, y);
            pointArray[4] = (short)Math.round(x[0]);
            pointArray[5] = (short)Math.round(y[0]);
            x[0] = rect.x;
            y[0] = rect.y + rect.height;
            Cairo.cairo_matrix_transform_point(matrix, x, y);
            pointArray[6] = (short)Math.round(x[0]);
            pointArray[7] = (short)Math.round(y[0]);
            int /*long*/ polyRgn = OS.XPolygonRegion(pointArray, pointArray.length / 2, OS.EvenOddRule);
            OS.XUnionRegion(handle, polyRgn, handle);
            OS.XDestroyRegion(polyRgn);
            OS.XDestroyRegion(clipRgn);
            data.clipRgn = newRgn;
      }
}
/** 
 * If the argument is <code>true</code>, puts the receiver
 * in a drawing mode where the resulting color in the destination
 * is the <em>exclusive or</em> of the color values in the source
 * and the destination, and if the argument is <code>false</code>,
 * puts the receiver in a drawing mode where the destination color
 * is replaced with the source color value.
 * <p>
 * Note that this mode in fundamentally unsupportable on certain
 * platforms, notably Carbon (Mac OS X). Clients that want their
 * code to run on all platforms need to avoid this method.
 * </p>
 *
 * @param xor if <code>true</code>, then <em>xor</em> mode is used, otherwise <em>source copy</em> mode is used
 *
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 * 
 * @deprecated this functionality is not supported on some platforms
 */
03939 public void setXORMode(boolean xor) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      OS.XSetFunction(data.display, handle, xor ? OS.GXxor : OS.GXcopy);
}
/**
 * Returns the extent of the given string. No tab
 * expansion or carriage return processing will be performed.
 * <p>
 * The <em>extent</em> of a string is the width and height of
 * the rectangular area it would cover if drawn in a particular
 * font (in this case, the current font in the receiver).
 * </p>
 *
 * @param string the string to measure
 * @return a point containing the extent of the string
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03962 public Point stringExtent(String string) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      setString(string);
      if (data.stringWidth != -1) return new Point(data.stringWidth, data.stringHeight);
      int width, height;
      if (string.length() == 0) {
            width = 0;
            height = getFontHeight();
      } else {
            int fontList = data.font.handle;
            int xmString = data.xmString;
            width = OS.XmStringWidth(fontList, xmString);
            height = OS.XmStringHeight(fontList, xmString);
      }
      return new Point(data.stringWidth = width, data.stringHeight = height);
}
/**
 * Returns the extent of the given string. Tab expansion and
 * carriage return processing are performed.
 * <p>
 * The <em>extent</em> of a string is the width and height of
 * the rectangular area it would cover if drawn in a particular
 * font (in this case, the current font in the receiver).
 * </p>
 *
 * @param string the string to measure
 * @return a point containing the extent of the string
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
03998 public Point textExtent(String string) {
      return textExtent(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
}
/**
 * Returns the extent of the given string. Tab expansion, line
 * delimiter and mnemonic processing are performed according to
 * the specified flags, which can be a combination of:
 * <dl>
 * <dt><b>DRAW_DELIMITER</b></dt>
 * <dd>draw multiple lines</dd>
 * <dt><b>DRAW_TAB</b></dt>
 * <dd>expand tabs</dd>
 * <dt><b>DRAW_MNEMONIC</b></dt>
 * <dd>underline the mnemonic character</dd>
 * <dt><b>DRAW_TRANSPARENT</b></dt>
 * <dd>transparent background</dd>
 * </dl>
 * <p>
 * The <em>extent</em> of a string is the width and height of
 * the rectangular area it would cover if drawn in a particular
 * font (in this case, the current font in the receiver).
 * </p>
 *
 * @param string the string to measure
 * @param flags the flags specifing how to process the text
 * @return a point containing the extent of the string
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the string is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
 * </ul>
 */
04032 public Point textExtent(String string, int flags) {
      if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
      if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
      setText(string, flags);
      if (data.textWidth != -1) return new Point(data.textWidth, data.textHeight);
      int width, height;
      if (string.length() == 0) {
            width = 0;
            height = getFontHeight();
      } else {
            int fontList = data.font.handle;
            int xmText = data.xmText;
            width = OS.XmStringWidth(fontList, xmText);
            height = OS.XmStringHeight(fontList, xmText);
      }
      return new Point(data.textWidth = width, data.textHeight = height);
}
/**
 * Returns a string containing a concise, human-readable
 * description of the receiver.
 *
 * @return a string representation of the receiver
 */
04055 public String toString () {
      if (isDisposed()) return "GC {*DISPOSED*}";
      return "GC {" + handle + "}";
}
}

Generated by  Doxygen 1.6.0   Back to index