summaryrefslogtreecommitdiffstats
path: root/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse
diff options
context:
space:
mode:
authorFelipe Heidrich <fheidric>2007-01-26 23:24:43 +0000
committerFelipe Heidrich <fheidric>2007-01-26 23:24:43 +0000
commit1c3e108eb7a60138c073a4a35f43be1e228cc3ec (patch)
tree9f9b0aae2e521d730026dfeb0c78f9bb0e0c3e53 /bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse
parent9e9b7c1991c514a5ce2c57186a01ce1662a5d135 (diff)
downloadeclipse.platform.swt-1c3e108eb7a60138c073a4a35f43be1e228cc3ec.tar.gz
eclipse.platform.swt-1c3e108eb7a60138c073a4a35f43be1e228cc3ec.tar.xz
eclipse.platform.swt-1c3e108eb7a60138c073a4a35f43be1e228cc3ec.zip
initial wpf release
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse')
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java285
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java478
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java588
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java23
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java302
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java508
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java132
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java2866
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java56
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java1145
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java578
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java195
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java720
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java1658
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java341
15 files changed, 9875 insertions, 0 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java
new file mode 100644
index 0000000000..824fb33fc7
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Color.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * 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.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class manage the operating system resources that
+ * implement SWT's RGB color model. To create a color you can either
+ * specify the individual color components as integers in the range
+ * 0 to 255 or provide an instance of an <code>RGB</code>.
+ * <p>
+ * Application code must explicitly invoke the <code>Color.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see RGB
+ * @see Device#getSystemColor
+ */
+
+public final class Color extends Resource {
+
+ /**
+ * the handle to the OS color resource
+ * (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;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Color() {
+}
+
+/**
+ * Constructs a new instance of this class given a device and the
+ * desired red, green and blue values expressed as ints in the range
+ * 0 to 255 (where 0 is black and 255 is full brightness). On limited
+ * color devices, the color instance created by this call may not have
+ * the same RGB values as the ones specified by the arguments. The
+ * RGB values on the returned instance will be the color values of
+ * the operating system color.
+ * <p>
+ * You must dispose the color when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param red the amount of red in the color
+ * @param green the amount of green in the color
+ * @param blue the amount of blue in the color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+public Color (Device device, int red, int green, int blue) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, red, green, blue);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new instance of this class given a device and an
+ * <code>RGB</code> describing the desired red, green and blue values.
+ * On limited color devices, the color instance created by this call
+ * may not have the same RGB values as the ones specified by the
+ * argument. The RGB values on the returned instance will be the color
+ * values of the operating system color.
+ * <p>
+ * You must dispose the color when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the color
+ * @param rgb the RGB values of the desired color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the rgb argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue components of the argument are not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+public Color (Device device, RGB rgb) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (rgb == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, rgb.red, rgb.green, rgb.blue);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the color. Applications must dispose of all colors which
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * 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
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Color)) return false;
+ Color color = (Color) object;
+ return device == color.device && (handle & 0xFFFFFF) == (color.handle & 0xFFFFFF);
+}
+
+/**
+ * Returns the amount of blue in the color, from 0 to 255.
+ *
+ * @return the blue component of the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getBlue () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Color_B(handle) & 0xFF;
+}
+
+/**
+ * Returns the amount of green in the color, from 0 to 255.
+ *
+ * @return the green component of the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getGreen () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Color_G(handle) & 0xFF;
+}
+
+/**
+ * Returns the amount of red in the color, from 0 to 255.
+ *
+ * @return the red component of the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getRed () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Color_R(handle) & 0xFF;
+}
+
+/**
+ * Returns an <code>RGB</code> representing the receiver.
+ *
+ * @return the RGB for the color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public RGB getRGB () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return new RGB(OS.Color_R(handle) & 0xFF, OS.Color_G(handle) & 0xFF, OS.Color_B(handle) & 0xFF);
+}
+
+/**
+ * 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
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * Allocates the operating system resources associated
+ * with the receiver.
+ *
+ * @param device the device on which to allocate the color
+ * @param red the amount of red in the color
+ * @param green the amount of green in the color
+ * @param blue the amount of blue in the color
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the red, green or blue argument is not between 0 and 255</li>
+ * </ul>
+ *
+ * @see #dispose
+ */
+void init(Device device, int red, int green, int blue) {
+ if (red > 255 || red < 0 || green > 255 || green < 0 || blue > 255 || blue < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.device = device;
+ handle = OS.Color_FromArgb((byte)0xFF, (byte)red, (byte)green, (byte)blue);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Returns <code>true</code> if the color has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the color.
+ * When a color has been disposed, it is an error to
+ * invoke any other method using the color.
+ *
+ * @return <code>true</code> when the color is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Color {*DISPOSED*}"; //$NON-NLS-1$
+ return "Color {" + getRed() + ", " + getGreen() + ", " + getBlue() + "}"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new color.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Color</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 device the device on which to allocate the color
+ * @param handle the handle for the color
+ * @return a new color object containing the specified device and handle
+ */
+public static Color wpf_new(Device device, int handle) {
+ if (device == null) device = Device.getDevice();
+ Color color = new Color();
+ color.handle = handle;
+ color.device = device;
+ return color;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java
new file mode 100644
index 0000000000..4d59e0abf6
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Cursor.java
@@ -0,0 +1,478 @@
+/*******************************************************************************
+ * 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.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class manage operating system resources that
+ * specify the appearance of the on-screen pointer. To create a
+ * cursor you specify the device and either a simple cursor style
+ * describing one of the standard operating system provided cursors
+ * or the image and mask data for the desired appearance.
+ * <p>
+ * Application code must explicitly invoke the <code>Cursor.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ * <dl>
+ * <dt><b>Styles:</b></dt>
+ * <dd>
+ * CURSOR_ARROW, CURSOR_WAIT, CURSOR_CROSS, CURSOR_APPSTARTING, CURSOR_HELP,
+ * CURSOR_SIZEALL, CURSOR_SIZENESW, CURSOR_SIZENS, CURSOR_SIZENWSE, CURSOR_SIZEWE,
+ * CURSOR_SIZEN, CURSOR_SIZES, CURSOR_SIZEE, CURSOR_SIZEW, CURSOR_SIZENE, CURSOR_SIZESE,
+ * CURSOR_SIZESW, CURSOR_SIZENW, CURSOR_UPARROW, CURSOR_IBEAM, CURSOR_NO, CURSOR_HAND
+ * </dd>
+ * </dl>
+ * <p>
+ * Note: Only one of the above styles may be specified.
+ * </p>
+ */
+
+public final class Cursor extends Resource {
+
+ /**
+ * the handle to the OS cursor resource
+ * (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;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Cursor() {
+}
+
+/**
+ * Constructs a new cursor given a device and a style
+ * constant describing the desired cursor appearance.
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param style the style of cursor to allocate
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT - when an unknown style is specified</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ *
+ * @see SWT#CURSOR_ARROW
+ * @see SWT#CURSOR_WAIT
+ * @see SWT#CURSOR_CROSS
+ * @see SWT#CURSOR_APPSTARTING
+ * @see SWT#CURSOR_HELP
+ * @see SWT#CURSOR_SIZEALL
+ * @see SWT#CURSOR_SIZENESW
+ * @see SWT#CURSOR_SIZENS
+ * @see SWT#CURSOR_SIZENWSE
+ * @see SWT#CURSOR_SIZEWE
+ * @see SWT#CURSOR_SIZEN
+ * @see SWT#CURSOR_SIZES
+ * @see SWT#CURSOR_SIZEE
+ * @see SWT#CURSOR_SIZEW
+ * @see SWT#CURSOR_SIZENE
+ * @see SWT#CURSOR_SIZESE
+ * @see SWT#CURSOR_SIZESW
+ * @see SWT#CURSOR_SIZENW
+ * @see SWT#CURSOR_UPARROW
+ * @see SWT#CURSOR_IBEAM
+ * @see SWT#CURSOR_NO
+ * @see SWT#CURSOR_HAND
+ */
+public Cursor(Device device, int style) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ switch (style) {
+ case SWT.CURSOR_HAND: handle = OS.Cursors_Hand(); break;
+ case SWT.CURSOR_ARROW: handle = OS.Cursors_Arrow(); break;
+ case SWT.CURSOR_WAIT: handle = OS.Cursors_Wait(); break;
+ case SWT.CURSOR_CROSS: handle = OS.Cursors_Cross(); break;
+ case SWT.CURSOR_APPSTARTING: handle = OS.Cursors_AppStarting(); break;
+ case SWT.CURSOR_HELP: handle = OS.Cursors_Help(); break;
+ case SWT.CURSOR_SIZEALL: handle = OS.Cursors_SizeAll(); break;
+ case SWT.CURSOR_SIZENESW: handle = OS.Cursors_SizeNESW(); break;
+ case SWT.CURSOR_SIZENS: handle = OS.Cursors_SizeNS(); break;
+ case SWT.CURSOR_SIZENWSE: handle = OS.Cursors_SizeNWSE(); break;
+ case SWT.CURSOR_SIZEWE: handle = OS.Cursors_SizeWE(); break;
+ case SWT.CURSOR_SIZEN: handle = OS.Cursors_ScrollN(); break;
+ case SWT.CURSOR_SIZES: handle = OS.Cursors_ScrollS(); break;
+ case SWT.CURSOR_SIZEE: handle = OS.Cursors_ScrollE(); break;
+ case SWT.CURSOR_SIZEW: handle = OS.Cursors_ScrollW(); break;
+ case SWT.CURSOR_SIZENE: handle = OS.Cursors_ScrollNE(); break;
+ case SWT.CURSOR_SIZESE: handle = OS.Cursors_ScrollSE(); break;
+ case SWT.CURSOR_SIZESW: handle = OS.Cursors_ScrollSW(); break;
+ case SWT.CURSOR_SIZENW: handle = OS.Cursors_ScrollNW(); break;
+ case SWT.CURSOR_UPARROW: handle = OS.Cursors_UpArrow(); break;
+ case SWT.CURSOR_IBEAM: handle = OS.Cursors_IBeam(); break;
+ case SWT.CURSOR_NO: handle = OS.Cursors_No(); break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new cursor given a device, image and mask
+ * data describing the desired cursor appearance, and the x
+ * and y coordinates of the <em>hotspot</em> (that is, the point
+ * within the area covered by the cursor which is considered
+ * to be where the on-screen pointer is "pointing").
+ * <p>
+ * The mask data is allowed to be null, but in this case the source
+ * must be an ImageData representing an icon that specifies both
+ * color data and mask data.
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the color data for the cursor
+ * @param mask the mask data for the cursor (or null)
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the source is null</li>
+ * <li>ERROR_NULL_ARGUMENT - if the mask is null and the source does not have a mask</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the source and the mask are not the same
+ * size, or if the hotspot is outside the bounds of the image</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ */
+public Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (mask == null) {
+ if (source.getTransparencyType() != SWT.TRANSPARENCY_MASK) {
+ SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ }
+ mask = source.getTransparencyMask();
+ }
+ /* Check the bounds. Mask must be the same size as source */
+ if (mask.width != source.width || mask.height != source.height) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ /* Check the hotspots */
+ if (hotspotX >= source.width || hotspotX < 0 ||
+ hotspotY >= source.height || hotspotY < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ /* Convert depth to 1 */
+ mask = ImageData.convertMask(mask);
+ source = ImageData.convertMask(source);
+
+ /* Make sure source and mask scanline pad is 2 */
+ byte[] sourceData = ImageData.convertPad(source.data, source.width, source.height, source.depth, source.scanlinePad, 2);
+ byte[] maskData = ImageData.convertPad(mask.data, mask.width, mask.height, mask.depth, mask.scanlinePad, 2);
+
+ /* Create the cursor */
+ int hInst = OS.GetModuleHandleW(null);
+ int cursor = OS.CreateCursor(hInst, hotspotX, hotspotY, source.width, source.height, sourceData, maskData);
+ if (cursor == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int safeHandle = OS.gcnew_SWTSafeHandle(cursor, false);
+ if (safeHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ handle = OS.CursorInteropHelper_Create(safeHandle);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(safeHandle);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new cursor given a device, image data describing
+ * the desired cursor appearance, and the x and y coordinates of
+ * the <em>hotspot</em> (that is, the point within the area
+ * covered by the cursor which is considered to be where the
+ * on-screen pointer is "pointing").
+ * <p>
+ * You must dispose the cursor when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the cursor
+ * @param source the image data for the cursor
+ * @param hotspotX the x coordinate of the cursor's hotspot
+ * @param hotspotY the y coordinate of the cursor's hotspot
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the hotspot is outside the bounds of the
+ * image</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a handle could not be obtained for cursor creation</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public Cursor(Device device, ImageData source, int hotspotX, int hotspotY) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ /* Check the hotspots */
+ if (hotspotX >= source.width || hotspotX < 0 ||
+ hotspotY >= source.height || hotspotY < 0) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ PaletteData palette = source.palette;
+ if (!(((source.depth == 1 || source.depth == 2 || source.depth == 4 || source.depth == 8) && !palette.isDirect) ||
+ ((source.depth == 8) || (source.depth == 16 || source.depth == 24 || source.depth == 32) && palette.isDirect)))
+ SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+ this.device = device;
+ int width = source.width;
+ int height = source.height;
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ ImageData newData = null;
+ int pixelFormat = 0;
+ boolean transparent = source.maskData != null || source.transparentPixel != -1 || source.alpha != -1 || source.alphaData != null;
+ if (transparent) {
+ pixelFormat = OS.PixelFormat_Format32bppArgb;
+ if (!(palette.isDirect && source.depth == 32 && redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
+ newData = new ImageData(width, height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ } else {
+ switch (source.depth) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ pixelFormat = OS.PixelFormat_Format24bppRgb;
+ newData = new ImageData(source.width, source.height, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));
+ break;
+ case 16:
+ if (redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F) {
+ pixelFormat = OS.PixelFormat_Format16bppRgb555;
+ } else if (redMask == 0xF800 && greenMask == 0x7E0 && blueMask == 0x1F) {
+ pixelFormat = OS.PixelFormat_Format16bppRgb565;
+ } else {
+ pixelFormat = OS.PixelFormat_Format16bppRgb555;
+ newData = new ImageData(source.width, source.height, 16, new PaletteData(0x7C00, 0x3E0, 0x1F));
+ }
+ break;
+ case 24:
+ if (redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000) {
+ pixelFormat = OS.PixelFormat_Format24bppRgb;
+ } else {
+ pixelFormat = OS.PixelFormat_Format24bppRgb;
+ newData = new ImageData(source.width, source.height, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));
+ }
+ break;
+ case 32:
+ if (redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000) {
+ pixelFormat = OS.PixelFormat_Format32bppRgb;
+ } else {
+ pixelFormat = OS.PixelFormat_Format32bppRgb;
+ newData = new ImageData(source.width, source.height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ break;
+ }
+ }
+ if (newData != null) {
+ PaletteData newPalette = newData.palette;
+ if (palette.isDirect) {
+ ImageData.blit(ImageData.BLIT_SRC,
+ source.data, source.depth, source.bytesPerLine, source.getByteOrder(), 0, 0, width, height, redMask, greenMask, blueMask,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ } else {
+ RGB[] rgbs = palette.getRGBs();
+ int length = rgbs.length;
+ byte[] srcReds = new byte[length];
+ byte[] srcGreens = new byte[length];
+ byte[] srcBlues = new byte[length];
+ for (int i = 0; i < rgbs.length; i++) {
+ RGB rgb = rgbs[i];
+ if (rgb == null) continue;
+ srcReds[i] = (byte)rgb.red;
+ srcGreens[i] = (byte)rgb.green;
+ srcBlues[i] = (byte)rgb.blue;
+ }
+ ImageData.blit(ImageData.BLIT_SRC,
+ source.data, source.depth, source.bytesPerLine, source.getByteOrder(), 0, 0, width, height, srcReds, srcGreens, srcBlues,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ }
+ if (source.transparentPixel != -1) {
+ newData.transparentPixel = newPalette.getPixel(palette.getRGB(source.transparentPixel));
+ }
+ newData.maskPad = source.maskPad;
+ newData.maskData = source.maskData;
+ newData.alpha = source.alpha;
+ newData.alphaData = source.alphaData;
+ source = newData;
+ palette = source.palette;
+ }
+ if (transparent) {
+ if (source.maskData != null || source.transparentPixel != -1) {
+ ImageData maskImage = source.getTransparencyMask();
+ byte[] maskData = maskImage.data;
+ int maskBpl = maskImage.bytesPerLine;
+ int offset = 3, maskOffset = 0;
+ for (int y = 0; y<height; y++) {
+ for (int x = 0; x<width; x++) {
+ source.data[offset] = ((maskData[maskOffset + (x >> 3)]) & (1 << (7 - (x & 0x7)))) != 0 ? (byte)0xff : 0;
+ offset += 4;
+ }
+ maskOffset += maskBpl;
+ }
+ } else if (source.alpha != -1) {
+ byte alpha = (byte)source.alpha;
+ for (int i = 3, j = 0; i < source.data.length; i+=4, j++) {
+ source.data[i] = alpha;
+ }
+ } else {
+ for (int i = 3, j = 0; i < source.data.length; i+=4, j++) {
+ source.data[i] = source.alphaData[j];
+ }
+ }
+ }
+ int bitmap = OS.gcnew_Bitmap(source.width, source.height, source.bytesPerLine, pixelFormat, source.data);
+ if (bitmap == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int hIcon = OS.Bitmap_GetHicon(bitmap);
+ if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ ICONINFO info = new ICONINFO();
+ OS.GetIconInfo(hIcon, info);
+ info.fIcon = false;
+ info.xHotspot = hotspotX;
+ info.yHotspot = hotspotY;
+ OS.DestroyIcon(hIcon);
+ hIcon = OS.CreateIconIndirect(info);
+ if (info.hbmColor != 0) OS.DeleteObject(info.hbmColor);
+ if (info.hbmMask != 0)OS.DeleteObject(info.hbmMask);
+ if (hIcon == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+
+ /* Create the cursor */
+ int safeHandle = OS.gcnew_SWTSafeHandle(hIcon, true);
+ if (safeHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ handle = OS.CursorInteropHelper_Create(safeHandle);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(safeHandle);
+ OS.GCHandle_Free(bitmap);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the cursor. Applications must dispose of all cursors which
+ * they allocate.
+ */
+public void dispose () {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * 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
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Cursor)) return false;
+ Cursor cursor = (Cursor) object;
+ return device == cursor.device && handle == cursor.handle;
+}
+
+/**
+ * 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
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * Returns <code>true</code> if the cursor has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the cursor.
+ * When a cursor has been disposed, it is an error to
+ * invoke any other method using the cursor.
+ *
+ * @return <code>true</code> when the cursor is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Cursor {*DISPOSED*}";
+ return "Cursor {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new cursor.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Cursor</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 device the device on which to allocate the color
+ * @param handle the handle for the cursor
+ * @return a new cursor object containing the specified device and handle
+ */
+public static Cursor wpf_new(Device device, int handle) {
+ if (device == null) device = Device.getDevice();
+ Cursor cursor = new Cursor();
+ cursor.handle = handle;
+ cursor.device = device;
+ return cursor;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java
new file mode 100644
index 0000000000..a1c637ad42
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Device.java
@@ -0,0 +1,588 @@
+/*******************************************************************************
+ * 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.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * This class is the abstract superclass of all device objects,
+ * such as the Display device and the Printer device. Devices
+ * can have a graphics context (GC) created for them, and they
+ * can be drawn on by sending messages to the associated GC.
+ */
+public abstract class Device implements Drawable {
+
+ /* Debugging */
+ public static boolean DEBUG;
+ boolean debug = DEBUG;
+ boolean tracking = DEBUG;
+ Error [] errors;
+ Object [] objects;
+
+ Color[] colors;
+
+ /* System Font */
+ Font systemFont;
+
+ boolean disposed;
+
+ final static Object CREATE_LOCK = new Object();
+
+ /*
+ * TEMPORARY CODE. When a graphics object is
+ * created and the device parameter is null,
+ * the current Display is used. This presents
+ * a problem because SWT graphics does not
+ * reference classes in SWT widgets. The correct
+ * fix is to remove this feature. Unfortunately,
+ * too many application programs rely on this
+ * feature.
+ *
+ * This code will be removed in the future.
+ */
+ protected static Device CurrentDevice;
+ protected static Runnable DeviceFinder;
+ static {
+ try {
+ Class.forName ("org.eclipse.swt.widgets.Display"); //$NON-NLS-1$
+ } catch (Throwable e) {}
+ }
+
+/*
+* TEMPORARY CODE.
+*/
+static synchronized Device getDevice () {
+ if (DeviceFinder != null) DeviceFinder.run();
+ Device device = CurrentDevice;
+ CurrentDevice = null;
+ return device;
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * You must dispose the device when it is no longer required.
+ * </p>
+ *
+ * @see #create
+ * @see #init
+ *
+ * @since 3.1
+ */
+public Device() {
+ this(null);
+}
+
+/**
+ * Constructs a new instance of this class.
+ * <p>
+ * You must dispose the device when it is no longer required.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #create
+ * @see #init
+ * @see DeviceData
+ */
+public Device(DeviceData data) {
+ synchronized (CREATE_LOCK) {
+ if (data != null) {
+ debug = data.debug;
+ tracking = data.tracking;
+ }
+ create (data);
+ init ();
+ if (tracking) {
+ errors = new Error [128];
+ objects = new Object [128];
+ }
+
+ /* Initialize the system font slot */
+ int fontFamily = OS.SystemFonts_MessageFontFamily();
+ int style = OS.SystemFonts_MessageFontStyle();
+ int weight = OS.SystemFonts_MessageFontWeight();
+ double size = OS.SystemFonts_MessageFontSize();
+ int typeface = OS.gcnew_Typeface(fontFamily, style, weight, OS.FontStretches_Normal);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(style);
+ OS.GCHandle_Free(weight);
+ systemFont = Font.wpf_new(this, typeface, size);
+ }
+}
+
+/**
+ * Throws an <code>SWTException</code> if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method <em>should</em> be called by
+ * device implementors to enforce the standard SWT invariants.
+ * <p>
+ * Currently, it is an error to invoke any method (other than
+ * <code>isDisposed()</code> and <code>dispose()</code>) on a
+ * device that has had its <code>dispose()</code> method called.
+ * </p><p>
+ * In future releases of SWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * <p>
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+protected void checkDevice () {
+ if (disposed) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
+}
+
+/**
+ * Creates the device in the operating system. If the device
+ * does not have a handle, this method may do nothing depending
+ * on the device.
+ * <p>
+ * This method is called before <code>init</code>.
+ * </p><p>
+ * Subclasses are supposed to reimplement this method and not
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @param data the DeviceData which describes the receiver
+ *
+ * @see #init
+ */
+protected void create (DeviceData data) {
+}
+
+/**
+ * Destroys the device in the operating system and releases
+ * the device's handle. If the device does not have a handle,
+ * this method may do nothing depending on the device.
+ * <p>
+ * This method is called after <code>release</code>.
+ * </p><p>
+ * Subclasses are supposed to reimplement this method and not
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #dispose
+ * @see #release
+ */
+protected void destroy () {
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the receiver. After this method has been invoked, the receiver
+ * will answer <code>true</code> when sent the message
+ * <code>isDisposed()</code>.
+ *
+ * @see #release
+ * @see #destroy
+ * @see #checkDevice
+ */
+public void dispose () {
+ if (isDisposed()) return;
+ checkDevice ();
+ release ();
+ destroy ();
+ disposed = true;
+ if (tracking) {
+ objects = null;
+ errors = null;
+ }
+}
+
+void dispose_Object (Object object) {
+ for (int i=0; i<objects.length; i++) {
+ if (objects [i] == object) {
+ objects [i] = null;
+ errors [i] = null;
+ return;
+ }
+ }
+}
+
+/**
+ * Returns a rectangle describing the receiver's size and location.
+ *
+ * @return the bounding rectangle
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getBounds () {
+ checkDevice ();
+ int width = (int) OS.SystemParameters_PrimaryScreenWidth();
+ int height = (int) OS.SystemParameters_PrimaryScreenHeight();
+ return new Rectangle (0, 0, width, height);
+}
+
+/**
+ * Returns a <code>DeviceData</code> based on the receiver.
+ * Modifications made to this <code>DeviceData</code> will not
+ * affect the receiver.
+ *
+ * @return a <code>DeviceData</code> containing the device's data and attributes
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see DeviceData
+ */
+public DeviceData getDeviceData () {
+ checkDevice();
+ DeviceData data = new DeviceData ();
+ data.debug = debug;
+ data.tracking = tracking;
+ int count = 0, length = 0;
+ if (tracking) length = objects.length;
+ for (int i=0; i<length; i++) {
+ if (objects [i] != null) count++;
+ }
+ int index = 0;
+ data.objects = new Object [count];
+ data.errors = new Error [count];
+ for (int i=0; i<length; i++) {
+ if (objects [i] != null) {
+ data.objects [index] = objects [i];
+ data.errors [index] = errors [i];
+ index++;
+ }
+ }
+ return data;
+}
+
+/**
+ * Returns a rectangle which describes the area of the
+ * receiver which is capable of displaying data.
+ *
+ * @return the client area
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getBounds
+ */
+public Rectangle getClientArea () {
+ return getBounds ();
+}
+
+/**
+ * Returns the bit depth of the screen, which is the number of
+ * bits it takes to represent the number of unique colors that
+ * the screen is currently capable of displaying. This number
+ * will typically be one of 1, 8, 15, 16, 24 or 32.
+ *
+ * @return the depth of the screen
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getDepth () {
+ checkDevice ();
+ //TODO - implement getDepth
+ return 32;
+}
+
+/**
+ * Returns a point whose x coordinate is the horizontal
+ * dots per inch of the display, and whose y coordinate
+ * is the vertical dots per inch of the display.
+ *
+ * @return the horizontal and vertical DPI
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Point getDPI () {
+ checkDevice ();
+ //TODO implement getDPI
+ return new Point(96, 96);
+}
+
+/**
+ * Returns <code>FontData</code> objects which describe
+ * the fonts that match the given arguments. If the
+ * <code>faceName</code> is null, all fonts will be returned.
+ *
+ * @param faceName the name of the font to look for, or null
+ * @param scalable if true only scalable fonts are returned, otherwise only non-scalable fonts are returned.
+ * @return the matching font data
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontData [] getFontList (String faceName, boolean scalable) {
+ checkDevice ();
+ if (!scalable) return new FontData[0];
+ int typefaces;
+ if (faceName != null) {
+ int length = faceName.length();
+ char[] chars = new char[length + 1];
+ faceName.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ int fontFamily = OS.gcnew_FontFamily(str);
+ typefaces = OS.FontFamily_GetTypefaces(fontFamily);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(str);
+ } else {
+ typefaces = OS.Fonts_SystemTypefaces();
+ }
+ int count = OS.TypefaceCollection_Count(typefaces);
+ int index = 0;
+ FontData[] result = new FontData[count];
+ int enumerator = OS.TypefaceCollection_GetEnumerator(typefaces);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int typeface = OS.TypefaceCollection_Current(enumerator);
+ int fontFamily = OS.Typeface_FontFamily(typeface);
+ int style = OS.Typeface_Style(typeface);
+ int weight = OS.Typeface_Weight(typeface);
+ int stretch = OS.Typeface_Stretch(typeface);
+ int str = OS.FontFamily_Source(fontFamily);
+ int charArray = OS.String_ToCharArray(str);
+ char[] chars = new char[OS.String_Length(str)];
+ OS.memmove(chars, charArray, chars.length * 2);
+ int fontStyle = OS.FontStyles_Normal;
+ if (OS.Object_Equals(style, OS.FontStyles_Italic)) fontStyle = OS.FontStyles_Italic;
+ if (OS.Object_Equals(style, OS.FontStyles_Oblique)) fontStyle = OS.FontStyles_Oblique;
+ FontData data = FontData.wpf_new(new String(chars), fontStyle,
+ OS.FontWeight_ToOpenTypeWeight(weight), OS.FontStretch_ToOpenTypeStretch(stretch), 0);
+ OS.GCHandle_Free(charArray);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(style);
+ OS.GCHandle_Free(weight);
+ OS.GCHandle_Free(stretch);
+ OS.GCHandle_Free(typeface);
+ result[index++] = data;
+ }
+ OS.GCHandle_Free(enumerator);
+ OS.GCHandle_Free(typefaces);
+ return result;
+}
+
+/**
+ * Returns the matching standard color for the given
+ * constant, which should be one of the color constants
+ * specified in class <code>SWT</code>. Any value other
+ * than one of the SWT color constants which is passed
+ * in will result in the color black. This color should
+ * not be freed because it was allocated by the system,
+ * not the application.
+ *
+ * @param id the color constant
+ * @return the matching color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see SWT
+ */
+public Color getSystemColor (int id) {
+ checkDevice ();
+ if (0 <= id && id < colors.length) {
+ return colors[id];
+ }
+ return colors[0];
+}
+
+/**
+ * Returns a reasonable font for applications to use.
+ * On some platforms, this will match the "default font"
+ * or "system font" if such can be found. This font
+ * should not be freed because it was allocated by the
+ * system, not the application.
+ * <p>
+ * Typically, applications which want the default look
+ * should simply not set the font on the widgets they
+ * create. Widgets are always created with the correct
+ * default font for the class of user-interface component
+ * they represent.
+ * </p>
+ *
+ * @return a font
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Font getSystemFont () {
+ checkDevice ();
+ return systemFont;
+}
+
+/**
+ * Returns <code>true</code> if the underlying window system prints out
+ * warning messages on the console, and <code>setWarnings</code>
+ * had previously been called with <code>true</code>.
+ *
+ * @return <code>true</code>if warnings are being handled, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean getWarnings () {
+ checkDevice ();
+ return false;
+}
+
+/**
+ * Initializes any internal resources needed by the
+ * device.
+ * <p>
+ * This method is called after <code>create</code>.
+ * </p><p>
+ * If subclasses reimplement this method, they must
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #create
+ */
+protected void init () {
+ /* Create the standard colors */
+ colors = new Color[SWT.COLOR_DARK_GRAY + 1];
+ colors[SWT.COLOR_BLACK] = colors[0] = Color.wpf_new(this, OS.Colors_Black());
+ colors[SWT.COLOR_DARK_RED] = Color.wpf_new(this, OS.Colors_Maroon ());
+ colors[SWT.COLOR_DARK_GREEN] = Color.wpf_new(this, OS.Colors_Green ());
+ colors[SWT.COLOR_DARK_YELLOW] = Color.wpf_new(this, OS.Colors_Olive());
+ colors[SWT.COLOR_DARK_BLUE] = Color.wpf_new(this, OS.Colors_Navy ());
+ colors[SWT.COLOR_DARK_MAGENTA] = Color.wpf_new(this, OS.Colors_Purple());
+ colors[SWT.COLOR_DARK_CYAN] = Color.wpf_new(this, OS.Colors_Teal ());
+ colors[SWT.COLOR_GRAY] = Color.wpf_new(this, OS.Colors_Silver ());
+ colors[SWT.COLOR_DARK_GRAY] = Color.wpf_new(this, OS.Colors_Silver ());
+ colors[SWT.COLOR_RED] = Color.wpf_new(this, OS.Colors_Red ());
+ colors[SWT.COLOR_GREEN] = Color.wpf_new(this, OS.Colors_Lime ());
+ colors[SWT.COLOR_YELLOW] = Color.wpf_new(this, OS.Colors_Yellow ());
+ colors[SWT.COLOR_BLUE] = Color.wpf_new(this, OS.Colors_Blue ());
+ colors[SWT.COLOR_MAGENTA] = Color.wpf_new(this, OS.Colors_Magenta ());
+ colors[SWT.COLOR_CYAN] = Color.wpf_new(this, OS.Colors_Cyan ());
+ colors[SWT.COLOR_WHITE] = Color.wpf_new(this, OS.Colors_White ());
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Device</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 data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public abstract int internal_new_GC (GCData data);
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Device</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 hDC the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public abstract void internal_dispose_GC (int hDC, GCData data);
+
+/**
+ * Returns <code>true</code> if the device has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the device.
+ * When a device has been disposed, it is an error to
+ * invoke any other method using the device.
+ *
+ * @return <code>true</code> when the device is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed () {
+ return disposed;
+}
+
+void new_Object (Object object) {
+ for (int i=0; i<objects.length; i++) {
+ if (objects [i] == null) {
+ objects [i] = object;
+ errors [i] = new Error ();
+ return;
+ }
+ }
+ Object [] newObjects = new Object [objects.length + 128];
+ System.arraycopy (objects, 0, newObjects, 0, objects.length);
+ newObjects [objects.length] = object;
+ objects = newObjects;
+ Error [] newErrors = new Error [errors.length + 128];
+ System.arraycopy (errors, 0, newErrors, 0, errors.length);
+ newErrors [errors.length] = new Error ();
+ errors = newErrors;
+}
+
+/**
+ * Releases any internal resources back to the operating
+ * system and clears all fields except the device handle.
+ * <p>
+ * When a device is destroyed, resources that were acquired
+ * on behalf of the programmer need to be returned to the
+ * operating system. For example, if the device allocated a
+ * font to be used as the system font, this font would be
+ * freed in <code>release</code>. Also,to assist the garbage
+ * collector and minimize the amount of memory that is not
+ * reclaimed when the programmer keeps a reference to a
+ * disposed device, all fields except the handle are zero'd.
+ * The handle is needed by <code>destroy</code>.
+ * </p>
+ * This method is called before <code>destroy</code>.
+ * </p><p>
+ * If subclasses reimplement this method, they must
+ * call the <code>super</code> implementation.
+ * </p>
+ *
+ * @see #dispose
+ * @see #destroy
+ */
+protected void release () {
+ for (int i = 0; i < colors.length; i++) {
+ if (colors[i] != null) colors[i].dispose();
+ }
+ colors = null;
+ if (systemFont != null) systemFont.dispose();
+ systemFont = null;
+}
+
+/**
+ * If the underlying window system supports printing warning messages
+ * to the console, setting warnings to <code>false</code> prevents these
+ * messages from being printed. If the argument is <code>true</code> then
+ * message printing is not blocked.
+ *
+ * @param warnings <code>true</code>if warnings should be printed, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setWarnings (boolean warnings) {
+ checkDevice ();
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java
new file mode 100644
index 0000000000..593b25584d
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/DeviceData.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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;
+
+
+public class DeviceData {
+ /*
+ * Debug fields - may not be honoured
+ * on some SWT platforms.
+ */
+ public boolean debug;
+ public boolean tracking;
+ public Error [] errors;
+ public Object [] objects;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java
new file mode 100644
index 0000000000..336c1c4914
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Font.java
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * 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.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class manage operating system resources that
+ * define how text looks when it is displayed. Fonts may be constructed
+ * by providing a device and either name, size and style information
+ * or a <code>FontData</code> object which encapsulates this data.
+ * <p>
+ * Application code must explicitly invoke the <code>Font.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see FontData
+ */
+
+public final class Font extends Resource {
+
+ /**
+ * the handle to the OS font resource
+ * (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;
+
+ /**
+ * the handle to the OS font resource
+ * (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 double size;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Font() {
+}
+
+/**
+ * Constructs a new font given a device and font data
+ * which describes the desired font's appearance.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param fd the FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the fd argument is null</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a font could not be created from the given font data</li>
+ * </ul>
+ */
+public Font(Device device, FontData fd) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, fd);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new font given a device and an array
+ * of font data which describes the desired font's
+ * appearance.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param fds the array of FontData that describes the desired font (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the fds argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the length of fds is zero</li>
+ * <li>ERROR_NULL_ARGUMENT - if any fd in the array is null</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a font could not be created from the given font data</li>
+ * </ul>
+ *
+ * @since 2.1
+ */
+public Font(Device device, FontData[] fds) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (fds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (fds.length == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ for (int i=0; i<fds.length; i++) {
+ if (fds[i] == null) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ init(device, fds[0]);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new font given a device, a font name,
+ * the height of the desired font in points, and a font
+ * style.
+ * <p>
+ * You must dispose the font when it is no longer required.
+ * </p>
+ *
+ * @param device the device to create the font on
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the name argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES - if a font could not be created from the given arguments</li>
+ * </ul>
+ */
+public Font(Device device, String name, int height, int style) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, new FontData (name, height, style));
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the font. Applications must dispose of all fonts which
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * 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
+ */
+public boolean equals(Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Font)) return false;
+ Font font = (Font) object;
+ return device == font.device && handle == font.handle && size == font.size;
+}
+
+/**
+ * Returns an array of <code>FontData</code>s representing the receiver.
+ * On Windows, only one FontData will be returned per font. On X however,
+ * a <code>Font</code> object <em>may</em> be composed of multiple X
+ * fonts. To support this case, we return an array of font data objects.
+ *
+ * @return an array of font data objects describing the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontData[] getFontData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int fontFamily = OS.Typeface_FontFamily(handle);
+ int style = OS.Typeface_Style(handle);
+ int weight = OS.Typeface_Weight(handle);
+ int stretch = OS.Typeface_Stretch(handle);
+ int str = OS.FontFamily_Source(fontFamily);
+ int charArray = OS.String_ToCharArray(str);
+ char[] chars = new char[OS.String_Length(str)];
+ OS.memmove(chars, charArray, chars.length * 2);
+ int fontStyle = OS.FontStyles_Normal;
+ if (OS.Object_Equals(style, OS.FontStyles_Italic)) fontStyle = OS.FontStyles_Italic;
+ if (OS.Object_Equals(style, OS.FontStyles_Oblique)) fontStyle = OS.FontStyles_Oblique;
+ int size = (int) (this.size * 72 / 96f);
+ FontData data = FontData.wpf_new(new String(chars), fontStyle, OS.FontWeight_ToOpenTypeWeight(weight), OS.FontStretch_ToOpenTypeStretch(stretch), (int)size);
+ OS.GCHandle_Free(charArray);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(style);
+ OS.GCHandle_Free(weight);
+ OS.GCHandle_Free(stretch);
+ return new FontData[] {data};
+}
+
+/**
+ * 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
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+void init (Device device, FontData fd) {
+ if (fd == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ int length = fd.fontFamily.length();
+ char[] chars = new char[length + 1];
+ fd.fontFamily.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ int fontFamily = OS.gcnew_FontFamily(str);
+ int style = fd.style;
+ int weight = OS.FontWeight_FromOpenTypeWeight(fd.weight);
+ int stretch = OS.FontStretch_FromOpenTypeStretch(fd.stretch);
+ handle = OS.gcnew_Typeface(fontFamily, style, weight, stretch);
+ OS.GCHandle_Free(fontFamily);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(weight);
+ OS.GCHandle_Free(stretch);
+ size = fd.height * 96 / 72f;
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Returns <code>true</code> if the font has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the font.
+ * When a font has been disposed, it is an error to
+ * invoke any other method using the font.
+ *
+ * @return <code>true</code> when the font is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Font {*DISPOSED*}";
+ return "Font {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Font</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 device the device on which to allocate the color
+ * @param handle the handle for the font
+ * @return a new font object containing the specified device and handle
+ */
+public static Font wpf_new(Device device, int handle, double size) {
+ if (device == null) device = Device.getDevice();
+ Font font = new Font();
+ font.handle = handle;
+ font.size = size;
+ font.device = device;
+ return font;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java
new file mode 100644
index 0000000000..fa35329588
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontData.java
@@ -0,0 +1,508 @@
+/*******************************************************************************
+ * 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.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class describe operating system fonts.
+ * <p>
+ * For platform-independent behaviour, use the get and set methods
+ * corresponding to the following properties:
+ * <dl>
+ * <dt>height</dt><dd>the height of the font in points</dd>
+ * <dt>name</dt><dd>the face name of the font, which may include the foundry</dd>
+ * <dt>style</dt><dd>A bitwise combination of NORMAL, ITALIC and BOLD</dd>
+ * </dl>
+ * If extra, platform-dependent functionality is required:
+ * <ul>
+ * <li>On <em>Windows</em>, the data member of the <code>FontData</code>
+ * corresponds to a Windows <code>LOGFONT</code> structure whose fields
+ * may be retrieved and modified.</li>
+ * <li>On <em>X</em>, the fields of the <code>FontData</code> correspond
+ * to the entries in the font's XLFD name and may be retrieved and modified.
+ * </ul>
+ * Application code does <em>not</em> need to explicitly release the
+ * resources managed by each instance when those instances are no longer
+ * required, and thus no <code>dispose()</code> method is provided.
+ *
+ * @see Font
+ */
+
+public final class FontData {
+
+ /**
+ * A WPF font
+ * (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 String fontFamily;
+
+ public int style;
+
+ public int weight;
+
+ public int stretch;
+
+ /**
+ * The height of the font data in points
+ * (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 height;
+
+ /**
+ * The locales of the font
+ */
+ String lang, country, variant;
+
+/**
+ * Constructs a new un-initialized font data.
+ */
+public FontData() {
+ fontFamily = "";
+ style = OS.FontStyles_Normal;
+ weight = OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Normal);
+ stretch = OS.FontStretch_ToOpenTypeStretch(OS.FontStretches_Normal);
+ height = 12;
+}
+
+/**
+ * Constructs a new FontData given a string representation
+ * in the form generated by the <code>FontData.toString</code>
+ * method.
+ * <p>
+ * Note that the representation varies between platforms,
+ * and a FontData can only be created from a string that was
+ * generated on the same platform.
+ * </p>
+ *
+ * @param string the string representation of a <code>FontData</code> (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument does not represent a valid description</li>
+ * </ul>
+ *
+ * @see #toString
+ */
+public FontData(String string) {
+ if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ int start = 0;
+ int end = string.indexOf('|');
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ String version1 = string.substring(start, end);
+ try {
+ if (Integer.parseInt(version1) != 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ String name = string.substring(start, end);
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int height = 0;
+ try {
+ height = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int style = 0;
+ try {
+ style = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+ if (end == -1) return;
+ String platform = string.substring(start, end);
+
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ String version2 = string.substring(start, end);
+
+ if (platform.equals("WPF") && version2.equals("1")) {
+ try {
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ fontFamily = string.substring(start, end);
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ String styleStr = string.substring(start, end);
+ int length = styleStr.length();
+ char[] chars = new char[length + 1];
+ styleStr.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ int converter = OS.TypeDescriptor_GetConverter(OS.FontStyles_Normal);
+ this.style = OS.FontStyles_Normal;
+ int fontStyle = OS.TypeConverter_ConvertFromString(converter, str);
+ if (fontStyle != 0) {
+ if (OS.Object_Equals(OS.FontStyles_Italic, fontStyle)) this.style = OS.FontStyles_Italic;
+ if (OS.Object_Equals(OS.FontStyles_Oblique, fontStyle)) this.style = OS.FontStyles_Oblique;
+ OS.GCHandle_Free(fontStyle);
+ }
+ OS.GCHandle_Free(converter);
+ OS.GCHandle_Free(str);
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) return;
+ weight = Integer.parseInt(string.substring(start, end));
+ start = end + 1;
+ end = string.indexOf('|', start);
+ if (end == -1) end = string.length();
+ stretch = Integer.parseInt(string.substring(start, end));
+ } catch (NumberFormatException e) {
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+ return;
+ }
+ }
+}
+
+/**
+ * Constructs a new font data given a font name,
+ * the height of the desired font in points,
+ * and a font style.
+ *
+ * @param name the name of the font (must not be null)
+ * @param height the font height in points
+ * @param style a bit or combination of NORMAL, BOLD, ITALIC
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - when the font name is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ */
+public FontData(String name, int height, int style) {
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ setName(name);
+ setHeight(height);
+ setStyle(style);
+ stretch = OS.FontStretch_ToOpenTypeStretch(OS.FontStretches_Normal);
+}
+
+/**
+ * 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
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof FontData)) return false;
+ FontData fd = (FontData)object;
+ return style == fd.style &&
+ height == fd.height &&
+ weight == fd.weight &&
+ stretch == fd.stretch &&
+ getName().equals(fd.getName());
+}
+
+/**
+ * Returns the height of the receiver in points.
+ *
+ * @return the height of this FontData
+ *
+ * @see #setHeight
+ */
+public int getHeight() {
+ return height;
+}
+
+/**
+ * Returns the locale of the receiver.
+ * <p>
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ * </p>
+ * <p>
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ * </p>
+ *
+ * @return the <code>String</code> representing a Locale object
+ * @since 3.0
+ */
+public String getLocale () {
+ StringBuffer buffer = new StringBuffer ();
+ char sep = '_';
+ if (lang != null) {
+ buffer.append (lang);
+ buffer.append (sep);
+ }
+ if (country != null) {
+ buffer.append (country);
+ buffer.append (sep);
+ }
+ if (variant != null) {
+ buffer.append (variant);
+ }
+
+ String result = buffer.toString ();
+ int length = result.length ();
+ if (length > 0) {
+ if (result.charAt (length - 1) == sep) {
+ result = result.substring (0, length - 1);
+ }
+ }
+ return result;
+}
+
+/**
+ * Returns the name of the receiver.
+ * On platforms that support font foundries, the return value will
+ * be the foundry followed by a dash ("-") followed by the face name.
+ *
+ * @return the name of this <code>FontData</code>
+ *
+ * @see #setName
+ */
+public String getName() {
+ return fontFamily;
+}
+
+/**
+ * Returns the style of the receiver which is a bitwise OR of
+ * one or more of the <code>SWT</code> constants NORMAL, BOLD
+ * and ITALIC.
+ *
+ * @return the style of this <code>FontData</code>
+ *
+ * @see #setStyle
+ */
+public int getStyle() {
+ int style = SWT.NORMAL;
+ if (weight == OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Bold)) style |= SWT.BOLD;
+ if (style == OS.FontStyles_Italic) style |= SWT.ITALIC;
+ return style;
+}
+
+/**
+ * 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
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return style ^ weight ^ stretch ^ getName().hashCode();
+}
+
+/**
+ * Sets the height of the receiver. The parameter is
+ * specified in terms of points, where a point is one
+ * seventy-second of an inch.
+ *
+ * @param height the height of the <code>FontData</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the height is negative</li>
+ * </ul>
+ *
+ * @see #getHeight
+ */
+public void setHeight(int height) {
+ if (height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.height = height;
+}
+
+/**
+ * Sets the locale of the receiver.
+ * <p>
+ * The locale determines which platform character set this
+ * font is going to use. Widgets and graphics operations that
+ * use this font will convert UNICODE strings to the platform
+ * character set of the specified locale.
+ * </p>
+ * <p>
+ * On platforms where there are multiple character sets for a
+ * given language/country locale, the variant portion of the
+ * locale will determine the character set.
+ * </p>
+ *
+ * @param locale the <code>String</code> representing a Locale object
+ * @see java.util.Locale#toString
+ */
+public void setLocale(String locale) {
+ lang = country = variant = null;
+ if (locale != null) {
+ char sep = '_';
+ int length = locale.length();
+ int firstSep, secondSep;
+
+ firstSep = locale.indexOf(sep);
+ if (firstSep == -1) {
+ firstSep = secondSep = length;
+ } else {
+ secondSep = locale.indexOf(sep, firstSep + 1);
+ if (secondSep == -1) secondSep = length;
+ }
+ if (firstSep > 0) lang = locale.substring(0, firstSep);
+ if (secondSep > firstSep + 1) country = locale.substring(firstSep + 1, secondSep);
+ if (length > secondSep + 1) variant = locale.substring(secondSep + 1);
+ }
+}
+
+/**
+ * Sets the name of the receiver.
+ * <p>
+ * Some platforms support font foundries. On these platforms, the name
+ * of the font specified in setName() may have one of the following forms:
+ * <ol>
+ * <li>a face name (for example, "courier")</li>
+ * <li>a foundry followed by a dash ("-") followed by a face name (for example, "adobe-courier")</li>
+ * </ol>
+ * In either case, the name returned from getName() will include the
+ * foundry.
+ * </p>
+ * <p>
+ * On platforms that do not support font foundries, only the face name
+ * (for example, "courier") is used in <code>setName()</code> and
+ * <code>getName()</code>.
+ * </p>
+ *
+ * @param name the name of the font data (must not be null)
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - when the font name is null</li>
+ * </ul>
+ *
+ * @see #getName
+ */
+public void setName(String name) {
+ if (name == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ fontFamily = name;
+}
+
+/**
+ * Sets the style of the receiver to the argument which must
+ * be a bitwise OR of one or more of the <code>SWT</code>
+ * constants NORMAL, BOLD and ITALIC. All other style bits are
+ * ignored.
+ *
+ * @param style the new style for this <code>FontData</code>
+ *
+ * @see #getStyle
+ */
+public void setStyle(int style) {
+ if ((style & SWT.BOLD) == SWT.BOLD) {
+ weight = OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Bold);
+ } else {
+ weight = OS.FontWeight_ToOpenTypeWeight(OS.FontWeights_Normal);
+ }
+ if ((style & SWT.ITALIC) == SWT.ITALIC) {
+ this.style = OS.FontStyles_Italic;
+ } else {
+ this.style = OS.FontStyles_Normal;
+ }
+}
+
+/**
+ * Returns a string representation of the receiver which is suitable
+ * for constructing an equivalent instance using the
+ * <code>FontData(String)</code> constructor.
+ *
+ * @return a string representation of the FontData
+ *
+ * @see FontData
+ */
+public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("1|"); //$NON-NLS-1$
+ buffer.append(getName());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(getHeight());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(getStyle());
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append("WPF|1|"); //$NON-NLS-1$
+ buffer.append(fontFamily);
+ buffer.append("|"); //$NON-NLS-1$
+ int converter = OS.TypeDescriptor_GetConverter(OS.FontStyles_Normal);
+ int str = OS.TypeConverter_ConvertToString(converter, style != 0 ? style : OS.FontStyles_Normal);
+ int charArray = OS.String_ToCharArray(str);
+ char[] chars = new char[OS.String_Length(str)];
+ OS.memmove(chars, charArray, chars.length * 2);
+ OS.GCHandle_Free (charArray);
+ OS.GCHandle_Free (str);
+ OS.GCHandle_Free (converter);
+ buffer.append(chars);
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(weight);
+ buffer.append("|"); //$NON-NLS-1$
+ buffer.append(stretch);
+ return buffer.toString();
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new font data.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>FontData</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 data the <code>LOGFONT</code> for the font data
+ * @param height the height of the font data
+ * @return a new font data object containing the specified <code>LOGFONT</code> and height
+ */
+public static FontData wpf_new(String fontFamily, int style, int weight, int stretch, int height) {
+ FontData data = new FontData();
+ data.fontFamily = fontFamily;
+ data.style = style;
+ data.weight = weight;
+ data.stretch = stretch;
+ data.height = height;
+ return data;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java
new file mode 100644
index 0000000000..51d98b7e6c
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/FontMetrics.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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;
+
+
+/**
+ * Instances of this class provide measurement information
+ * about fonts including ascent, descent, height, leading
+ * space between rows, and average character width.
+ * <code>FontMetrics</code> are obtained from <code>GC</code>s
+ * using the <code>getFontMetrics()</code> method.
+ *
+ * @see GC#getFontMetrics
+ */
+public final class FontMetrics {
+ int ascent, descent, averageCharWidth, leading, height;
+
+FontMetrics() {
+}
+
+/**
+ * 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
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof FontMetrics)) return false;
+ FontMetrics metrics = (FontMetrics)object;
+ return ascent == metrics.ascent && descent == metrics.descent &&
+ averageCharWidth == metrics.averageCharWidth && leading == metrics.leading &&
+ height == metrics.height;
+}
+
+/**
+ * Returns the ascent of the font described by the receiver. A
+ * font's <em>ascent</em> is the distance from the baseline to the
+ * top of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the ascent of the font
+ */
+public int getAscent() {
+ return ascent;
+}
+
+/**
+ * Returns the average character width, measured in pixels,
+ * of the font described by the receiver.
+ *
+ * @return the average character width of the font
+ */
+public int getAverageCharWidth() {
+ return averageCharWidth;
+}
+
+/**
+ * Returns the descent of the font described by the receiver. A
+ * font's <em>descent</em> is the distance from the baseline to the
+ * bottom of actual characters, not including any of the leading area,
+ * measured in pixels.
+ *
+ * @return the descent of the font
+ */
+public int getDescent() {
+ return descent;
+}
+
+/**
+ * Returns the height of the font described by the receiver,
+ * measured in pixels. A font's <em>height</em> is the sum of
+ * its ascent, descent and leading area.
+ *
+ * @return the height of the font
+ *
+ * @see #getAscent
+ * @see #getDescent
+ * @see #getLeading
+ */
+public int getHeight() {
+ return height;
+}
+
+/**
+ * Returns the leading area of the font described by the
+ * receiver. A font's <em>leading area</em> is the space
+ * above its ascent which may include accents or other marks.
+ *
+ * @return the leading space of the font
+ */
+public int getLeading() {
+ return leading;
+}
+
+/**
+ * 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
+ *
+ * @see #equals
+ */
+public int hashCode() {
+ return ascent ^ descent ^ averageCharWidth ^ leading ^ height;
+}
+
+public static FontMetrics wpf_new(int ascent, int descent, int averageCharWidth, int leading, int height) {
+ FontMetrics fontMetrics = new FontMetrics();
+ fontMetrics.ascent = ascent;
+ fontMetrics.descent = descent;
+ fontMetrics.averageCharWidth = averageCharWidth;
+ fontMetrics.leading = leading;
+ fontMetrics.height = height;
+ return fontMetrics;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java
new file mode 100644
index 0000000000..f12d2127a5
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GC.java
@@ -0,0 +1,2866 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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.wpf.*;
+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 FOREGROUND = 1 << 0;
+ static final int BACKGROUND = 1 << 1;
+ static final int FONT = 1 << 2;
+ static final int LINE_STYLE = 1 << 3;
+ static final int LINE_WIDTH = 1 << 4;
+ static final int LINE_CAP = 1 << 5;
+ static final int LINE_JOIN = 1 << 6;
+ static final int ALPHA = 1 << 7;
+ static final int CLIPPING = 1 << 8;
+ static final int TRANSFORM = 1 << 9;
+
+ static final int DRAW = FOREGROUND | LINE_STYLE | LINE_WIDTH | LINE_CAP | LINE_JOIN | ALPHA | CLIPPING | TRANSFORM;
+ static final int FILL = BACKGROUND | ALPHA | CLIPPING | TRANSFORM;
+
+ static final double[] LINE_DOT_ZERO = new double[]{3, 3};
+ static final double[] LINE_DASH_ZERO = new double[]{18, 6};
+ static final double[] LINE_DASHDOT_ZERO = new double[]{9, 6, 3, 6};
+ static final double[] LINE_DASHDOTDOT_ZERO = new double[]{9, 3, 3, 3, 3, 3};
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+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>
+ */
+public GC(Drawable drawable) {
+ this(drawable, SWT.NONE);
+}
+
+/**
+ * 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
+ */
+public GC(Drawable drawable, int style) {
+ if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ GCData data = new GCData ();
+ data.style = checkStyle(style);
+ int hDC = 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, hDC);
+ 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);
+}
+
+void checkGC(int mask) {
+ int state = data.state;
+ if ((state & mask) == mask) return;
+ state = (state ^ mask) & mask;
+ data.state |= mask;
+ if ((state & (FOREGROUND | LINE_WIDTH | LINE_STYLE | LINE_JOIN | LINE_CAP)) != 0) {
+ int pen = data.pen;
+ if (pen != 0) OS.GCHandle_Free(pen);
+ pen = data.pen = OS.gcnew_Pen();
+ int brush;
+ Pattern pattern = data.foregroundPattern;
+ if (pattern != null) {
+ brush = pattern.handle;
+ } else {
+ int foreground = data.foreground;
+ brush = OS.gcnew_SolidColorBrush(foreground);
+ if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ }
+ OS.Pen_Brush(pen, brush);
+ if (pattern == null) OS.GCHandle_Free(brush);
+ int width = data.lineWidth;
+ OS.Pen_Thickness(pen, Math.max (1, width));
+ double[] dashes = null;
+ int dashStyle = 0;
+ switch (data.lineStyle) {
+ case SWT.LINE_SOLID: dashStyle = OS.DashStyles_Solid(); break;
+ case SWT.LINE_DOT: if (width == 0) dashes = LINE_DOT_ZERO; else dashStyle = OS.DashStyles_Dot(); break;
+ case SWT.LINE_DASH: if (width == 0) dashes = LINE_DASH_ZERO; else dashStyle = OS.DashStyles_Dash(); break;
+ case SWT.LINE_DASHDOT: if (width == 0) dashes = LINE_DASHDOT_ZERO; else dashStyle = OS.DashStyles_DashDot(); break;
+ case SWT.LINE_DASHDOTDOT: if (width == 0) dashes = LINE_DASHDOTDOT_ZERO; else dashStyle = OS.DashStyles_DashDotDot(); break;
+ case SWT.LINE_CUSTOM: {
+ if (data.lineDashes != null) {
+ dashes = new double[data.lineDashes.length * 2];
+ for (int i = 0; i < data.lineDashes.length; i++) {
+ double dash = (double)data.lineDashes[i] / Math.max (1, width);
+ dashes[i] = dash;
+ dashes[i + data.lineDashes.length] = dash;
+ }
+ } else {
+ dashStyle = OS.DashStyles_Solid();
+ }
+ }
+ }
+ if (dashes != null) {
+ int list = OS.gcnew_DoubleCollection(dashes.length);
+ for (int i = 0; i < dashes.length; i++) {
+ OS.DoubleCollection_Add(list, dashes[i]);
+ }
+ dashStyle = OS.gcnew_DashStyle(list, 0);
+ OS.GCHandle_Free(list);
+ }
+ OS.Pen_DashStyle(pen, dashStyle);
+ OS.GCHandle_Free(dashStyle);
+ int joinStyle = 0;
+ switch (data.lineJoin) {
+ case SWT.JOIN_MITER: joinStyle = OS.PenLineJoin_Miter; break;
+ case SWT.JOIN_BEVEL: joinStyle = OS.PenLineJoin_Bevel; break;
+ case SWT.JOIN_ROUND: joinStyle = OS.PenLineJoin_Round; break;
+ }
+ OS.Pen_LineJoin(pen, joinStyle);
+ int capStyle = OS.PenLineCap_Flat;
+ switch (data.lineCap) {
+ case SWT.CAP_FLAT: capStyle = OS.PenLineCap_Flat; break;
+ case SWT.CAP_ROUND: capStyle = OS.PenLineCap_Round; break;
+ case SWT.CAP_SQUARE: capStyle = OS.PenLineCap_Square; break;
+ }
+ OS.Pen_DashCap(pen, capStyle);
+ OS.Pen_EndLineCap(pen, capStyle);
+ OS.Pen_StartLineCap(pen, capStyle);
+ }
+ if ((state & BACKGROUND) != 0) {
+ if (data.brush != 0) OS.GCHandle_Free(data.brush);
+ Pattern pattern = data.backgroundPattern;
+ if (pattern != null) {
+ data.currentBrush = pattern.handle;
+ } else {
+ int background = data.background;
+ int brush = OS.gcnew_SolidColorBrush(background);
+ if (brush == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ data.currentBrush = data.brush = brush;
+ }
+ }
+ if ((state & (ALPHA | CLIPPING | TRANSFORM)) != 0) {
+ for (int i = 0; i < data.pushCount; i++) OS.DrawingContext_Pop(handle);
+ data.pushCount = 0;
+ if (data.alpha != 0xFF) {
+ OS.DrawingContext_PushOpacity(handle, (data.alpha & 0xFF) / (double)0xFF);
+ data.pushCount++;
+ }
+ if (data.clip != 0) {
+ OS.DrawingContext_PushClip(handle, data.clip);
+ data.pushCount++;
+ }
+ if (data.transform != 0) {
+ OS.DrawingContext_PushTransform(handle, data.transform);
+ data.pushCount++;
+ }
+ }
+
+}
+
+/**
+ * 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>
+ */
+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);
+
+ //TODO - implement copyArea
+}
+
+/**
+ * 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>
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY) {
+ copyArea(srcX, srcY, 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
+ */
+public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+
+ //TODO - implement copyArea
+
+// /*
+// * Feature in WinCE. The function WindowFromDC is not part of the
+// * WinCE SDK. The fix is to remember the HWND.
+// */
+// int hwnd = data.hwnd;
+// if (hwnd == 0) {
+// OS.BitBlt(handle, destX, destY, width, height, handle, srcX, srcY, OS.SRCCOPY);
+// } else {
+// RECT lprcClip = null;
+// int hrgn = OS.CreateRectRgn(0, 0, 0, 0);
+// if (OS.GetClipRgn(handle, hrgn) == 1) {
+// lprcClip = new RECT();
+// OS.GetRgnBox(hrgn, lprcClip);
+// }
+// OS.DeleteObject(hrgn);
+// RECT lprcScroll = new RECT();
+// OS.SetRect(lprcScroll, srcX, srcY, srcX + width, srcY + height);
+// int flags = paint ? OS.SW_INVALIDATE | OS.SW_ERASE : 0;
+// int res = OS.ScrollWindowEx(hwnd, destX - srcX, destY - srcY, lprcScroll, lprcClip, 0, null, flags);
+//
+// /*
+// * Feature in WinCE. ScrollWindowEx does not accept combined
+// * vertical and horizontal scrolling. The fix is to do a
+// * BitBlt and invalidate the appropriate source area.
+// */
+// if (res == 0 && OS.IsWinCE) {
+// OS.BitBlt(handle, destX, destY, width, height, handle, srcX, srcY, OS.SRCCOPY);
+// if (paint) {
+// int deltaX = destX - srcX, deltaY = destY - srcY;
+// boolean disjoint = (destX + width < srcX) || (srcX + width < destX) || (destY + height < srcY) || (srcY + height < destY);
+// if (disjoint) {
+// OS.InvalidateRect(hwnd, lprcScroll, true);
+// } else {
+// if (deltaX != 0) {
+// int newX = destX - deltaX;
+// if (deltaX < 0) newX = destX + width;
+// OS.SetRect(lprcScroll, newX, srcY, newX + Math.abs(deltaX), srcY + height);
+// OS.InvalidateRect(hwnd, lprcScroll, true);
+// }
+// if (deltaY != 0) {
+// int newY = destY - deltaY;
+// if (deltaY < 0) newY = destY + height;
+// OS.SetRect(lprcScroll, srcX, newY, srcX + width, newY + Math.abs(deltaY));
+// OS.InvalidateRect(hwnd, lprcScroll, true);
+// }
+// }
+// }
+// }
+// }
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the graphics context. Applications must dispose of all GCs
+ * which they allocate.
+ */
+public void dispose() {
+ if (handle == 0) return;
+ if (data.device.isDisposed()) return;
+
+ int brush = data.brush;
+ if (brush != 0) OS.GCHandle_Free(brush);
+ data.brush = 0;
+ int pen = data.brush;
+ if (pen != 0) OS.GCHandle_Free(pen);
+ data.pen = 0;
+ int clip = data.clip;
+ if (clip != 0) OS.GCHandle_Free(clip);
+ data.clip = 0;
+ int transform = data.transform;
+ if (transform != 0) OS.GCHandle_Free(transform);
+ data.transform = 0;
+
+ Image image = data.image;
+ if (image != null) image.memGC = null;
+
+ Device device = data.device;
+ if (drawable != null) drawable.internal_dispose_GC(handle, data);
+ 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>
+ */
+public void drawArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ if (arcAngle >= 360 || arcAngle <= -360) {
+ int center = OS.gcnew_Point(x + offset + width / 2f, y + offset + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, 0, data.pen, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+ return;
+ }
+ boolean isNegative = arcAngle < 0;
+ boolean isLargeAngle = arcAngle > 180 || arcAngle < -180;
+ arcAngle = arcAngle + startAngle;
+ if (isNegative) {
+ // swap angles
+ int tmp = startAngle;
+ startAngle = arcAngle;
+ arcAngle = tmp;
+ }
+ double x1 = Math.cos(startAngle * Math.PI / 180) * width/2.0 + x + offset + width/2.0;
+ double y1 = -1 * Math.sin(startAngle * Math.PI / 180) * height/2.0 + y + offset + height/2.0;
+ double x2 = Math.cos(arcAngle * Math.PI / 180) * width/2.0 + x + offset + width/2.0;
+ double y2 = -1 * Math.sin(arcAngle * Math.PI / 180) * height/2.0 + y + offset + height/2.0;
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endPoint = OS.gcnew_Point(x2, y2);
+ int size = OS.gcnew_Size(width / 2.0, height / 2.0);
+ int arc = OS.gcnew_ArcSegment(endPoint, size, 0, isLargeAngle, OS.SweepDirection_Clockwise, true);
+ int figure = OS.gcnew_PathFigure();
+ OS.PathFigure_StartPoint(figure, startPoint);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, arc);
+ int path = OS.gcnew_PathGeometry();
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ OS.DrawingContext_DrawGeometry(handle, 0, data.pen, path);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(arc);
+ OS.GCHandle_Free(size);
+ OS.GCHandle_Free(endPoint);
+ OS.GCHandle_Free(startPoint);
+}
+
+/**
+ * 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)
+ */
+public void drawFocus (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ //TODO - implement drawFocus
+}
+
+/**
+ * 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>
+ */
+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>
+ */
+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 image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {
+ int imageHandle = image.handle;
+ int imgWidth = OS.BitmapSource_PixelWidth(imageHandle);
+ int imgHeight = OS.BitmapSource_PixelHeight(imageHandle);
+ 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);
+ }
+ }
+ int mode = 0;
+ switch (data.interpolation) {
+ case SWT.DEFAULT: mode = OS.BitmapScalingMode_Unspecified; break;
+ case SWT.NONE: mode = OS.BitmapScalingMode_LowQuality; break;
+ case SWT.LOW: mode = OS.BitmapScalingMode_LowQuality; break;
+ case SWT.HIGH: mode = OS.BitmapScalingMode_HighQuality; break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (srcX != 0 || srcY != 0 || srcWidth != imgWidth || srcHeight != imgHeight) {
+ int rect = OS.gcnew_Int32Rect(srcX, srcY, srcWidth, srcHeight);
+ imageHandle = OS.gcnew_CroppedBitmap(imageHandle, rect);
+ OS.RenderOptions_SetBitmapScalingMode(imageHandle, mode);
+ OS.GCHandle_Free(rect);
+ } else {
+ if (mode != OS.RenderOptions_GetBitmapScalingMode(imageHandle)) {
+ imageHandle = OS.Freezable_Clone(imageHandle);
+ OS.RenderOptions_SetBitmapScalingMode(imageHandle, mode);
+ }
+ }
+ int rect = OS.gcnew_Rect(destX, destY, destWidth, destHeight);
+ OS.DrawingContext_DrawImage(handle, imageHandle, rect);
+ OS.GCHandle_Free(rect);
+ if (image.handle != imageHandle) OS.GCHandle_Free(imageHandle);
+}
+
+/**
+ * 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>
+ */
+public void drawLine (int x1, int y1, int x2, int y2) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int point0 = OS.gcnew_Point(x1 + offset, y1 + offset);
+ int point1 = OS.gcnew_Point(x2 + offset, y2 + offset);
+ OS.DrawingContext_DrawLine(handle, data.pen, point0, point1);
+ OS.GCHandle_Free(point0);
+ OS.GCHandle_Free(point1);
+}
+
+/**
+ * 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>
+ */
+public void drawOval (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int center = OS.gcnew_Point(x + offset + width / 2f, y + offset + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, 0, data.pen, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+}
+
+/**
+ * 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
+ */
+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);
+ checkGC(DRAW);
+ //TODO - check offset to draw in the midle of pixel
+ OS.PathGeometry_FillRule(path.handle, data.fillRule == SWT.FILL_EVEN_ODD ? OS.FillRule_EvenOdd : OS.FillRule_Nonzero);
+ OS.DrawingContext_DrawGeometry(handle, 0, data.pen, path.handle);
+}
+
+/**
+ * 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
+ */
+public void drawPoint (int x, int y) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ int rect = OS.gcnew_Rect(x, y, 1, 1);
+ int brush = OS.Pen_Brush(data.pen);
+ OS.DrawingContext_DrawRectangle(handle, brush, 0, rect);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * 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>
+ */
+public void drawPolygon(int[] pointArray) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ checkGC(DRAW);
+ drawPolyLineSegment(pointArray, true, true);
+}
+
+void drawPolyLineSegment(int[] pointArray, boolean closed, boolean stroked) {
+ if (pointArray.length < 4) return;
+ int list = OS.gcnew_PointCollection(pointArray.length / 2);
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ for (int i = 0; i < pointArray.length; i += 2) {
+ int point = OS.gcnew_Point(pointArray[i] + offset, pointArray[i + 1] + offset);
+ OS.PointCollection_Add(list, point);
+ OS.GCHandle_Free(point);
+ }
+ int poly = OS.gcnew_PolyLineSegment(list, stroked);
+ OS.GCHandle_Free(list);
+ int figure = OS.gcnew_PathFigure();
+ int startPoint = OS.gcnew_Point(pointArray[0], pointArray[1]);
+ OS.PathFigure_StartPoint(figure, startPoint);
+ OS.PathFigure_IsClosed(figure, closed);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, poly);
+ int path = OS.gcnew_PathGeometry();
+// int mode = 0;
+// switch (data.antialias) {
+// case SWT.DEFAULT:
+// case SWT.ON: mode = OS.EdgeMode_Unspecified; break;
+// case SWT.OFF: mode = OS.EdgeMode_Aliased; break;
+// }
+// OS.RenderOptions_SetEdgeMode(path, mode);
+// OS.PathGeometry_FillRule(path, data.fillRule == SWT.FILL_EVEN_ODD ? OS.FillRule_EvenOdd : OS.FillRule_Nonzero);
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ OS.DrawingContext_DrawGeometry(handle, stroked ? 0 : data.brush, stroked ? data.pen : 0, path);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(startPoint);
+ OS.GCHandle_Free(poly);
+}
+
+/**
+ * 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>
+ */
+public void drawPolyline(int[] pointArray) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ checkGC(DRAW);
+ drawPolyLineSegment(pointArray, false, true);
+}
+
+/**
+ * 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>
+ */
+public void drawRectangle (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int rect = OS.gcnew_Rect(x + offset, y + offset, width, height);
+ OS.DrawingContext_DrawRectangle(handle, 0, data.pen, rect);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * 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>
+ */
+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>
+ */
+public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (arcWidth < 0 || arcHeight < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ checkGC(DRAW);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (arcWidth < 0) arcWidth = -arcWidth;
+ if (arcHeight < 0) arcHeight = -arcHeight;
+ double offset = 0;
+ if (data.lineWidth == 0 || (data.lineWidth % 2) == 1) offset = 0.5;
+ int rect = OS.gcnew_Rect(x + offset, y + offset, width, height);
+ OS.DrawingContext_DrawRoundedRectangle(handle, 0, data.pen, rect, arcWidth / 2f, arcHeight / 2f);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * 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>
+ */
+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>
+ */
+public void drawString (String string, int x, int y, boolean isTransparent) {
+ drawText(string, x, y, isTransparent ? SWT.DRAW_TRANSPARENT : 0);
+}
+
+/**
+ * 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>
+ */
+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>
+ */
+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>
+ */
+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);
+ int length = string.length ();
+ if (length == 0) return;
+ checkGC(FONT | FOREGROUND | ALPHA | CLIPPING | TRANSFORM | ((flags & SWT.DRAW_TRANSPARENT) != 0 ? 0 : BACKGROUND));
+ char [] buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ if ((flags & (SWT.DRAW_DELIMITER | SWT.DRAW_TAB)) != (SWT.DRAW_DELIMITER | SWT.DRAW_TAB)) {
+ for (int i = 0, j = 0; i < buffer.length; i++) {
+ char c = buffer[i];
+ switch (c) {
+ case '\r':
+ case '\n':
+ if ((flags & SWT.DRAW_DELIMITER) == 0) continue;
+ break;
+ case '\t':
+ if ((flags & SWT.DRAW_TAB) == 0) continue;
+ break;
+ }
+ buffer[j++] = c;
+ }
+ }
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ Font font = data.font;
+ int direction = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Pen_Brush(data.pen);
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ int point = OS.gcnew_Point(x, y);
+ if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
+ double width = OS.FormattedText_WidthIncludingTrailingWhitespace(text);
+ double height = OS.FormattedText_Height(text);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRectangle(handle, data.currentBrush, 0, rect);
+ OS.GCHandle_Free(rect);
+
+ }
+ OS.DrawingContext_DrawText(handle, text, point);
+ OS.GCHandle_Free(point);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(text);
+}
+
+/**
+ * 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
+ */
+public boolean equals (Object object) {
+ return (object == this) || ((object instanceof GC) && (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
+ */
+public void fillArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (width == 0 || height == 0 || arcAngle == 0) return;
+ if (arcAngle >= 360 || arcAngle <= -360) {
+ int center = OS.gcnew_Point(x + width / 2f, y + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, data.brush, 0, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+ return;
+ }
+ boolean isNegative = arcAngle < 0;
+ boolean isLargeAngle = arcAngle > 180 || arcAngle < -180;
+ arcAngle = arcAngle + startAngle;
+ if (isNegative) {
+ // swap angles
+ int tmp = startAngle;
+ startAngle = arcAngle;
+ arcAngle = tmp;
+ }
+ double x1 = Math.cos(startAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y1 = -1 * Math.sin(startAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ double x2 = Math.cos(arcAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y2 = -1 * Math.sin(arcAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endPoint = OS.gcnew_Point(x2, y2);
+ int center = OS.gcnew_Point(x + width / 2.0, y + height / 2.0);
+ int size = OS.gcnew_Size(width / 2.0, height / 2.0);
+ int arc = OS.gcnew_ArcSegment(endPoint, size, 0, isLargeAngle, OS.SweepDirection_Clockwise, false);
+ int line = OS.gcnew_LineSegment(center, false);
+ int figure = OS.gcnew_PathFigure();
+ OS.PathFigure_StartPoint(figure, startPoint);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, arc);
+ OS.PathSegmentCollection_Add(segments, line);
+ int path = OS.gcnew_PathGeometry();
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ OS.DrawingContext_DrawGeometry(handle, data.brush, 0, path);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(arc);
+ OS.GCHandle_Free(line);
+ OS.GCHandle_Free(size);
+ OS.GCHandle_Free(endPoint);
+ OS.GCHandle_Free(startPoint);
+}
+
+/**
+ * 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)
+ */
+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;
+ checkGC(FILL);
+
+ int fromColor = data.foreground;
+ int toColor = data.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) {
+ int temp = fromColor;
+ fromColor = toColor;
+ toColor = temp;
+ }
+ int brush = OS.gcnew_LinearGradientBrush(fromColor, toColor, vertical ? 90 : 0);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRectangle(handle, brush, 0, rect);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(brush);
+}
+
+/**
+ * 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
+ */
+public void fillOval (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ int center = OS.gcnew_Point(x + width / 2f, y + height / 2f);
+ OS.DrawingContext_DrawEllipse(handle, data.currentBrush, 0, center, width / 2f, height / 2f);
+ OS.GCHandle_Free(center);
+}
+
+/**
+ * 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
+ */
+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);
+ checkGC(FILL);
+ OS.PathGeometry_FillRule(path.handle, data.fillRule == SWT.FILL_EVEN_ODD ? OS.FillRule_EvenOdd : OS.FillRule_Nonzero);
+ OS.DrawingContext_DrawGeometry(handle, data.brush, 0, path.handle);
+}
+
+/**
+ * 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
+ */
+public void fillPolygon(int[] pointArray) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ checkGC(FILL);
+ drawPolyLineSegment(pointArray, true, false);
+}
+
+/**
+ * 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)
+ */
+public void fillRectangle (int x, int y, int width, int height) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRectangle(handle, data.currentBrush, 0, rect);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * 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)
+ */
+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
+ */
+public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FILL);
+ if (width < 0) {
+ x = x + width;
+ width = -width;
+ }
+ if (height < 0) {
+ y = y + height;
+ height = -height;
+ }
+ if (arcWidth < 0) arcWidth = -arcWidth;
+ if (arcHeight < 0) arcHeight = -arcHeight;
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ OS.DrawingContext_DrawRoundedRectangle(handle, data.currentBrush, 0, rect, arcWidth / 2f, arcHeight / 2f);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * 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>
+ */
+public int getAdvanceWidth(char ch) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ //NOT DONE
+ return stringExtent(new String(new char[]{ch})).x;
+}
+
+/**
+ * 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
+ */
+public boolean getAdvanced() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return true;
+}
+
+/**
+ * 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
+ */
+public int getAlpha() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.alpha;
+}
+
+/**
+ * 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
+ */
+public int getAntialias() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ 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>
+ */
+public Color getBackground() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return Color.wpf_new(data.device, data.background);
+}
+
+/**
+ * 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
+ */
+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>
+ */
+public int getCharWidth(char ch) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ //NOT DONE
+ return stringExtent(new String(new char[]{ch})).x;
+}
+
+/**
+ * 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>
+ */
+public Rectangle getClipping() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int x = 0, y = 0, width = 0, height = 0;
+ int visualType = OS.Object_GetType(data.visual);
+ int drawingVisualType = OS.DrawingVisual_typeid();
+ if (OS.Object_Equals(visualType, drawingVisualType)) {
+ int clip = OS.ContainerVisual_Clip(data.visual);
+ int rect = OS.Geometry_Bounds(clip);
+ width = (int)OS.Rect_Width(rect);
+ height = (int)OS.Rect_Height(rect);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(clip);
+ } else {
+ width = (int)OS.FrameworkElement_ActualWidth(data.visual);
+ height = (int)OS.FrameworkElement_ActualHeight(data.visual);
+ }
+ OS.GCHandle_Free(drawingVisualType);
+ OS.GCHandle_Free(visualType);
+ if (data.clip != 0) {
+ int bounds = OS.gcnew_Rect(x, y, width, height);
+ int rect = OS.Geometry_Bounds(data.clip);
+ OS.Rect_Intersect(bounds, rect);
+ x = (int)OS.Rect_X(bounds);
+ y = (int)OS.Rect_Y(bounds);
+ width = (int)OS.Rect_Width(bounds);
+ height = (int)OS.Rect_Height(bounds);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(bounds);
+ }
+ return new Rectangle(x, y, width, 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>
+ */
+public void getClipping (Region region) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ int bounds;
+ int visualType = OS.Object_GetType(data.visual);
+ int drawingVisualType = OS.DrawingVisual_typeid();
+ if (OS.Object_Equals(visualType, drawingVisualType)) {
+ bounds = OS.ContainerVisual_Clip(data.visual);
+ } else {
+ double width = OS.FrameworkElement_ActualWidth(data.visual);
+ double height = OS.FrameworkElement_ActualHeight(data.visual);
+ int rect = OS.gcnew_Rect(0, 0, width, height);
+ bounds = OS.gcnew_RectangleGeometry(rect);
+ OS.GCHandle_Free(rect);
+ }
+ OS.GCHandle_Free(drawingVisualType);
+ OS.GCHandle_Free(visualType);
+ int geometries = OS.GeometryGroup_Children(region.handle);
+ OS.GeometryCollection_Clear(geometries);
+ if (data.clip != 0) {
+ int clip = OS.Geometry_GetFlattenedPathGeometry(data.clip);
+ int newGeometry = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Intersect, bounds, clip);
+ OS.GeometryCollection_Add(geometries, newGeometry);
+ OS.GCHandle_Free(clip);
+ OS.GCHandle_Free(newGeometry);
+ } else {
+ OS.GeometryCollection_Add(geometries, bounds);
+ }
+ OS.GCHandle_Free(bounds);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * 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
+ */
+public int getFillRule() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.fillRule;
+}
+
+/**
+ * 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>
+ */
+public Font getFont () {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.font;
+}
+
+/**
+ * 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>
+ */
+public FontMetrics getFontMetrics() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ checkGC(FONT);
+ //TODO - find a better way of getting font metrics
+ String string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ int length = string.length();
+ char [] buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ Font font = data.font;
+ int direction = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ double width = OS.FormattedText_WidthIncludingTrailingWhitespace(text);
+ double height = OS.FormattedText_Height(text);
+ double baseline = OS.FormattedText_Baseline(text);
+ OS.GCHandle_Free(text);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ return FontMetrics.wpf_new((int)baseline, (int)(height - baseline), (int)width / string.length(), 0, (int)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>
+ */
+public Color getForeground() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return Color.wpf_new(data.device, data.foreground);
+}
+
+/**
+ * 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
+ */
+public Pattern getForegroundPattern() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.foregroundPattern;
+}
+
+/**
+ * Returns the GCData.
+ * <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>
+ *
+ * @return the receiver's GCData
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see GCData
+ *
+ * @since 3.2
+ */
+public GCData getGCData() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data;
+}
+
+/**
+ * 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
+ */
+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
+ */
+public int getLineCap() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.lineCap;
+}
+
+/**
+ * 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
+ */
+public int[] getLineDash() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineDashes == null) return null;
+ int[] lineDashes = new int[data.lineDashes.length];
+ System.arraycopy(data.lineDashes, 0, lineDashes, 0, lineDashes.length);
+ return lineDashes;
+}
+
+/**
+ * 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
+ */
+public int getLineJoin() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.lineJoin;
+}
+
+/**
+ * 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>
+ */
+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>
+ */
+public int getLineWidth() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.lineWidth;
+}
+
+/**
+ * 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
+ */
+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
+ */
+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
+ */
+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);
+ if (data.transform != 0) {
+ OS.MatrixTransform_Matrix(transform.handle, data.transform);
+ } 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>
+ */
+public boolean getXORMode() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.xorMode;
+}
+
+void init(Drawable drawable, GCData data, int hDC) {
+ int foreground = data.foreground;
+ if (foreground != -1) data.state &= ~FOREGROUND;
+ int background = data.background;
+ if (background != 0) data.state &= ~BACKGROUND;
+ Font font = data.font;
+ if (font != null) data.state &= ~FONT;
+ Image image = data.image;
+ if (image != null) image.memGC = this;
+// int layout = data.layout;
+// if (layout != -1) {
+// if (!OS.IsWinCE && OS.WIN32_VERSION >= OS.VERSION(4, 10)) {
+// int flags = OS.GetLayout(hDC);
+// if ((flags & OS.LAYOUT_RTL) != (layout & OS.LAYOUT_RTL)) {
+// flags &= ~OS.LAYOUT_RTL;
+// OS.SetLayout(hDC, flags | layout);
+// }
+// if ((data.style & SWT.RIGHT_TO_LEFT) != 0) data.style |= SWT.MIRRORED;
+// }
+// }
+ this.drawable = drawable;
+ this.data = data;
+ handle = hDC;
+}
+
+/**
+ * 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
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * 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>
+ */
+public boolean isClipped() {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return data.clip != 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
+ */
+public boolean isDisposed() {
+ return handle == 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
+ */
+public void setAdvanced(boolean advanced) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (!advanced) {
+ setAlpha(0xFF);
+ setAntialias(SWT.DEFAULT);
+ setBackgroundPattern(null);
+ setClipping((Rectangle)null);
+ setForegroundPattern(null);
+ setInterpolation(SWT.DEFAULT);
+ setTextAntialias(SWT.DEFAULT);
+ setTransform(null);
+ }
+}
+
+/**
+ * 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
+ */
+public void setAntialias(int antialias) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (antialias) {
+ case SWT.DEFAULT:
+ case SWT.OFF:
+ case SWT.ON:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.antialias = antialias;
+}
+
+/**
+ * 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
+ */
+public void setAlpha(int alpha) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ data.alpha = alpha & 0xFF;
+ data.state &= ~ALPHA;
+}
+
+/**
+ * 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>
+ */
+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);
+ if (data.backgroundPattern == null && data.background == color.handle) return;
+ data.backgroundPattern = null;
+ data.background = color.handle;
+ data.state &= ~BACKGROUND;
+}
+
+/**
+ * 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
+ */
+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.backgroundPattern == pattern) return;
+ data.backgroundPattern = pattern;
+ data.state &= ~BACKGROUND;
+}
+
+/**
+ * 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>
+ */
+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;
+ }
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int clip = OS.gcnew_RectangleGeometry(rect);
+ OS.GCHandle_Free(rect);
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = clip;
+ data.state &= ~CLIPPING;
+}
+
+/**
+ * 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
+ */
+public void setClipping (Path path) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path != null && path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = path != null ? OS.Geometry_Clone(path.handle) : 0;
+ data.state &= ~CLIPPING;
+}
+
+/**
+ * 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>
+ */
+public void setClipping (Rectangle rect) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) {
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = 0;
+ data.state &= ~CLIPPING;
+ } 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>
+ */
+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);
+ if (data.clip != 0) OS.GCHandle_Free(data.clip);
+ data.clip = region != null ? OS.Geometry_Clone(region.handle) : 0;
+ data.state &= ~CLIPPING;
+}
+
+/**
+ * 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
+ */
+public void setFillRule(int rule) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (rule) {
+ case SWT.FILL_WINDING:
+ case SWT.FILL_EVEN_ODD: break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.fillRule = rule;
+}
+
+/**
+ * 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>
+ */
+public void setFont (Font font) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ data.font = font != null ? font : data.device.systemFont;
+ data.state &= ~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>
+ */
+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);
+ if (data.foregroundPattern == null && color.handle == data.foreground) return;
+ data.foregroundPattern = null;
+ data.foreground = color.handle;
+ data.state &= ~FOREGROUND;
+}
+
+/**
+ * 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
+ */
+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.foregroundPattern == pattern) return;
+ data.foregroundPattern = pattern;
+ data.state &= ~FOREGROUND;
+}
+
+/**
+ * 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
+ */
+public void setInterpolation(int interpolation) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (interpolation) {
+ case SWT.DEFAULT: break;
+ case SWT.NONE: break;
+ case SWT.LOW: break;
+ case SWT.HIGH: break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ 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
+ */
+public void setLineCap(int cap) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineCap == cap) return;
+ switch (cap) {
+ case SWT.CAP_ROUND:
+ case SWT.CAP_FLAT:
+ case SWT.CAP_SQUARE:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.lineCap = cap;
+ data.state &= ~LINE_CAP;
+}
+
+/**
+ * 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
+ */
+public void setLineDash(int[] dashes) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int[] lineDashes = data.lineDashes;
+ if (dashes != null && dashes.length > 0) {
+ boolean changed = data.lineStyle != SWT.LINE_CUSTOM || lineDashes == null || lineDashes.length != dashes.length;
+ for (int i = 0; i < dashes.length; i++) {
+ int dash = dashes[i];
+ if (dash <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (!changed && lineDashes[i] != dash) changed = true;
+ }
+ if (!changed) return;
+ data.lineDashes = new int[dashes.length];
+ System.arraycopy(dashes, 0, data.lineDashes, 0, dashes.length);
+ data.lineStyle = SWT.LINE_CUSTOM;
+ } else {
+ if (data.lineStyle == SWT.LINE_SOLID && (lineDashes == null || lineDashes.length == 0)) return;
+ data.lineDashes = null;
+ data.lineStyle = SWT.LINE_SOLID;
+ }
+ data.state &= ~LINE_STYLE;
+}
+
+/**
+ * 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
+ */
+public void setLineJoin(int join) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineJoin == join) return;
+ switch (join) {
+ case SWT.JOIN_MITER:
+ case SWT.JOIN_ROUND:
+ case SWT.JOIN_BEVEL:
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.lineJoin = join;
+ data.state &= ~LINE_JOIN;
+}
+
+/**
+ * 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>
+ */
+public void setLineStyle(int lineStyle) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineStyle == lineStyle) return;
+ switch (lineStyle) {
+ case SWT.LINE_SOLID:
+ case SWT.LINE_DASH:
+ case SWT.LINE_DOT:
+ case SWT.LINE_DASHDOT:
+ case SWT.LINE_DASHDOTDOT:
+ break;
+ case SWT.LINE_CUSTOM:
+ if (data.lineDashes == null) lineStyle = SWT.LINE_SOLID;
+ break;
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ data.lineStyle = lineStyle;
+ data.state &= ~LINE_STYLE;
+}
+
+/**
+ * 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>
+ */
+public void setLineWidth(int lineWidth) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (data.lineWidth == lineWidth) return;
+ data.lineWidth = lineWidth;
+ data.state &= ~LINE_WIDTH;
+ switch (data.lineStyle) {
+ case SWT.LINE_DOT:
+ case SWT.LINE_DASH:
+ case SWT.LINE_DASHDOT:
+ case SWT.LINE_DASHDOTDOT:
+ data.state &= ~LINE_STYLE;
+ }
+}
+
+/**
+ * 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
+ */
+public void setXORMode(boolean xor) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ data.xorMode = xor;
+}
+
+/**
+ * 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
+ */
+public void setTextAntialias(int antialias) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ switch (antialias) {
+ case SWT.DEFAULT:
+ case SWT.OFF:
+ 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
+ */
+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);
+ data.transform = transform != null ? OS.gcnew_MatrixTransform(transform.handle) : 0;
+ data.state &= ~TRANSFORM;
+}
+
+/**
+ * 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>
+ */
+public Point stringExtent(String string) {
+ return textExtent(string, 0);
+}
+
+/**
+ * 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>
+ */
+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>
+ */
+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);
+ checkGC(FONT);
+ int length = string.length();
+ char [] buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ if ((flags & (SWT.DRAW_DELIMITER | SWT.DRAW_TAB)) != (SWT.DRAW_DELIMITER | SWT.DRAW_TAB)) {
+ for (int i = 0, j = 0; i < buffer.length; i++) {
+ char c = buffer[i];
+ switch (c) {
+ case '\r':
+ case '\n':
+ if ((flags & SWT.DRAW_DELIMITER) == 0) continue;
+ break;
+ case '\t':
+ if ((flags & SWT.DRAW_TAB) == 0) continue;
+ break;
+ }
+ buffer[j++] = c;
+ }
+ }
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ Font font = data.font;
+ int direction = (data.style & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ double width = OS.FormattedText_WidthIncludingTrailingWhitespace(text);
+ double height = OS.FormattedText_Height(text);
+ OS.GCHandle_Free(text);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ return new Point((int)width, (int)height);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "GC {*DISPOSED*}";
+ return "GC {" + handle + "}";
+}
+
+/**
+ * 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>
+ */
+public static GC wpf_new(Drawable drawable, GCData data) {
+ GC gc = new GC();
+ int hDC = drawable.internal_new_GC(data);
+ gc.device = data.device;
+ gc.init(drawable, data, hDC);
+ 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 hDC the Windows HDC.
+ * @param data the data for the receiver.
+ *
+ * @return a new <code>GC</code>
+ */
+public static GC wpf_new(int hDC, GCData data) {
+ GC gc = new GC();
+ gc.device = data.device;
+ gc.init(null, data, hDC);
+ return gc;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java
new file mode 100644
index 0000000000..90d3583d39
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/GCData.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.*;
+
+/**
+ * Instances of this class are descriptions of GCs in terms
+ * of unallocated platform-specific data fields.
+ * <p>
+ * <b>IMPORTANT:</b> This class is <em>not</em> part of the public
+ * API for SWT. 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>
+ */
+
+public final class GCData {
+ public Device device;
+ public int style, state = -1;
+ public int foreground;
+ public int background;
+ public Font font;
+ public Pattern foregroundPattern;
+ public Pattern backgroundPattern;
+ public boolean xorMode;
+ public int fillRule = SWT.FILL_EVEN_ODD;
+ public int interpolation = SWT.DEFAULT;
+ public int antialias = SWT.DEFAULT;
+ public int textAntialias = SWT.DEFAULT;
+ public int lineStyle = SWT.LINE_SOLID;
+ public int lineWidth;
+ public int lineCap = SWT.CAP_FLAT;
+ public int lineJoin = SWT.JOIN_MITER;
+ public int[] lineDashes;
+ public int alpha = 0xFF;
+
+ public Image image;
+ public int pen;
+ public int brush, currentBrush;
+ public int pushCount;
+ public int clip;
+ public int transform;
+ public int visual;
+ public int drawingContext;
+ public int renderHandle;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java
new file mode 100644
index 0000000000..0a486f12f9
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Image.java
@@ -0,0 +1,1145 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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.wpf.*;
+import org.eclipse.swt.*;
+
+import java.io.*;
+
+/**
+ * Instances of this class are graphics which have been prepared
+ * for display on a specific device. That is, they are ready
+ * to paint using methods such as <code>GC.drawImage()</code>
+ * and display on widgets with, for example, <code>Button.setImage()</code>.
+ * <p>
+ * If loaded from a file format that supports it, an
+ * <code>Image</code> may have transparency, meaning that certain
+ * pixels are specified as being transparent when drawn. Examples
+ * of file formats that support transparency are GIF and PNG.
+ * </p><p>
+ * There are two primary ways to use <code>Images</code>.
+ * The first is to load a graphic file from disk and create an
+ * <code>Image</code> from it. This is done using an <code>Image</code>
+ * constructor, for example:
+ * <pre>
+ * Image i = new Image(device, "C:\\graphic.bmp");
+ * </pre>
+ * A graphic file may contain a color table specifying which
+ * colors the image was intended to possess. In the above example,
+ * these colors will be mapped to the closest available color in
+ * SWT. It is possible to get more control over the mapping of
+ * colors as the image is being created, using code of the form:
+ * <pre>
+ * ImageData data = new ImageData("C:\\graphic.bmp");
+ * RGB[] rgbs = data.getRGBs();
+ * // At this point, rgbs contains specifications of all
+ * // the colors contained within this image. You may
+ * // allocate as many of these colors as you wish by
+ * // using the Color constructor Color(RGB), then
+ * // create the image:
+ * Image i = new Image(device, data);
+ * </pre>
+ * <p>
+ * Applications which require even greater control over the image
+ * loading process should use the support provided in class
+ * <code>ImageLoader</code>.
+ * </p><p>
+ * Application code must explicitly invoke the <code>Image.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @see Color
+ * @see ImageData
+ * @see ImageLoader
+ */
+
+public final class Image extends Resource implements Drawable {
+
+ /**
+ * specifies whether the receiver is a bitmap or an icon
+ * (one of <code>SWT.BITMAP</code>, <code>SWT.ICON</code>)
+ * <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 type;
+
+ /**
+ * the handle to the OS image resource
+ * (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;
+
+ /**
+ * specifies the transparent pixel
+ */
+ int transparentPixel = -1;
+
+ /**
+ * the GC which is drawing on the image
+ */
+ GC memGC;
+
+ /**
+ * the alpha data for the image
+ */
+ byte[] alphaData;
+
+ /**
+ * the global alpha value to be used for every pixel
+ */
+ int alpha = -1;
+
+ /**
+ * the image data used to create this image if it is a
+ * icon. Used only in WinCE
+ */
+ ImageData data;
+
+ /**
+ * width of the image
+ */
+ int width = -1;
+
+ /**
+ * height of the image
+ */
+ int height = -1;
+
+ /**
+ * specifies the default scanline padding
+ */
+ static final int DEFAULT_SCANLINE_PAD = 4;
+
+/**
+ * Prevents uninitialized instances from being created outside the package.
+ */
+Image () {
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * specified width and height. The result may be drawn upon
+ * by creating a GC and using any of its drawing operations,
+ * as shown in the following example:
+ * <pre>
+ * Image i = new Image(device, width, height);
+ * GC gc = new GC(i);
+ * gc.drawRectangle(0, 0, 50, 50);
+ * gc.dispose();
+ * </pre>
+ * <p>
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ * </p>
+ *
+ * @param device the device on which to create the image
+ * @param width the width of the new image
+ * @param height the height of the new image
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either the width or height is negative or zero</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, int width, int height) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, width, height);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new instance of this class based on the
+ * provided image, with an appearance that varies depending
+ * on the value of the flag. The possible flag values are:
+ * <dl>
+ * <dt><b>IMAGE_COPY</b></dt>
+ * <dd>the result is an identical copy of srcImage</dd>
+ * <dt><b>IMAGE_DISABLE</b></dt>
+ * <dd>the result is a copy of srcImage which has a <em>disabled</em> look</dd>
+ * <dt><b>IMAGE_GRAY</b></dt>
+ * <dd>the result is a copy of srcImage which has a <em>gray scale</em> look</dd>
+ * </dl>
+ *
+ * @param device the device on which to create the image
+ * @param srcImage the image to use as the source
+ * @param flag the style, either <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code>
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if srcImage is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the flag is not one of <code>IMAGE_COPY</code>, <code>IMAGE_DISABLE</code> or <code>IMAGE_GRAY</code></li>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon, or is otherwise in an invalid state</li>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the image is not supported</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, Image srcImage, int flag) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ Rectangle rect = srcImage.getBounds();
+ switch (flag) {
+ case SWT.IMAGE_COPY: {
+ type = srcImage.type;
+ handle = OS.BitmapSource_Clone(srcImage.handle);
+ transparentPixel = srcImage.transparentPixel;
+ alpha = srcImage.alpha;
+ if (srcImage.alphaData != null) {
+ alphaData = new byte[srcImage.alphaData.length];
+ System.arraycopy(srcImage.alphaData, 0, alphaData, 0, alphaData.length);
+ }
+ if (device.tracking) device.new_Object(this);
+ return;
+ }
+ case SWT.IMAGE_DISABLE: {
+ ImageData data = srcImage.getImageData();
+ PaletteData palette = data.palette;
+ RGB[] rgbs = new RGB[3];
+ rgbs[0] = device.getSystemColor(SWT.COLOR_BLACK).getRGB();
+ rgbs[1] = device.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW).getRGB();
+ rgbs[2] = device.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).getRGB();
+ ImageData newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
+ newData.alpha = data.alpha;
+ newData.alphaData = data.alphaData;
+ newData.maskData = data.maskData;
+ newData.maskPad = data.maskPad;
+ if (data.transparentPixel != -1) newData.transparentPixel = 0;
+
+ /* Convert the pixels. */
+ int[] scanline = new int[rect.width];
+ int[] maskScanline = null;
+ ImageData mask = null;
+ if (data.maskData != null) mask = data.getTransparencyMask();
+ if (mask != null) maskScanline = new int[rect.width];
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ int redShift = palette.redShift;
+ int greenShift = palette.greenShift;
+ int blueShift = palette.blueShift;
+ for (int y=0; y<rect.height; y++) {
+ int offset = y * newData.bytesPerLine;
+ data.getPixels(0, y, rect.width, scanline, 0);
+ if (mask != null) mask.getPixels(0, y, rect.width, maskScanline, 0);
+ for (int x=0; x<rect.width; x++) {
+ int pixel = scanline[x];
+ if (!(pixel == data.transparentPixel || (mask != null && maskScanline[x] == 0))) {
+ int red, green, blue;
+ if (palette.isDirect) {
+ red = pixel & redMask;
+ red = (redShift < 0) ? red >>> -redShift : red << redShift;
+ green = pixel & greenMask;
+ green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
+ blue = pixel & blueMask;
+ blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
+ } else {
+ red = palette.colors[pixel].red;
+ green = palette.colors[pixel].green;
+ blue = palette.colors[pixel].blue;
+ }
+ int intensity = red * red + green * green + blue * blue;
+ if (intensity < 98304) {
+ newData.data[offset] = (byte)1;
+ } else {
+ newData.data[offset] = (byte)2;
+ }
+ }
+ offset++;
+ }
+ }
+ init (device, newData);
+ if (device.tracking) device.new_Object(this);
+ return;
+ }
+ case SWT.IMAGE_GRAY: {
+ ImageData data = srcImage.getImageData();
+ PaletteData palette = data.palette;
+ ImageData newData = data;
+ if (!palette.isDirect) {
+ /* Convert the palette entries to gray. */
+ RGB [] rgbs = palette.getRGBs();
+ for (int i=0; i<rgbs.length; i++) {
+ if (data.transparentPixel != i) {
+ RGB color = rgbs [i];
+ int red = color.red;
+ int green = color.green;
+ int blue = color.blue;
+ int intensity = (red+red+green+green+green+green+green+blue) >> 3;
+ color.red = color.green = color.blue = intensity;
+ }
+ }
+ newData.palette = new PaletteData(rgbs);
+ } else {
+ /* Create a 8 bit depth image data with a gray palette. */
+ RGB[] rgbs = new RGB[256];
+ for (int i=0; i<rgbs.length; i++) {
+ rgbs[i] = new RGB(i, i, i);
+ }
+ newData = new ImageData(rect.width, rect.height, 8, new PaletteData(rgbs));
+ newData.alpha = data.alpha;
+ newData.alphaData = data.alphaData;
+ newData.maskData = data.maskData;
+ newData.maskPad = data.maskPad;
+ if (data.transparentPixel != -1) newData.transparentPixel = 254;
+
+ /* Convert the pixels. */
+ int[] scanline = new int[rect.width];
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ int redShift = palette.redShift;
+ int greenShift = palette.greenShift;
+ int blueShift = palette.blueShift;
+ for (int y=0; y<rect.height; y++) {
+ int offset = y * newData.bytesPerLine;
+ data.getPixels(0, y, rect.width, scanline, 0);
+ for (int x=0; x<rect.width; x++) {
+ int pixel = scanline[x];
+ if (pixel != data.transparentPixel) {
+ int red = pixel & redMask;
+ red = (redShift < 0) ? red >>> -redShift : red << redShift;
+ int green = pixel & greenMask;
+ green = (greenShift < 0) ? green >>> -greenShift : green << greenShift;
+ int blue = pixel & blueMask;
+ blue = (blueShift < 0) ? blue >>> -blueShift : blue << blueShift;
+ int intensity = (red+red+green+green+green+green+green+blue) >> 3;
+ if (newData.transparentPixel == intensity) intensity = 255;
+ newData.data[offset] = (byte)intensity;
+ } else {
+ newData.data[offset] = (byte)254;
+ }
+ offset++;
+ }
+ }
+ }
+ init (device, newData);
+ if (device.tracking) device.new_Object(this);
+ return;
+ }
+ default:
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+}
+
+/**
+ * Constructs an empty instance of this class with the
+ * width and height of the specified rectangle. The result
+ * may be drawn upon by creating a GC and using any of its
+ * drawing operations, as shown in the following example:
+ * <pre>
+ * Image i = new Image(device, boundsRectangle);
+ * GC gc = new GC(i);
+ * gc.drawRectangle(0, 0, 50, 50);
+ * gc.dispose();
+ * </pre>
+ * <p>
+ * Note: Some platforms may have a limitation on the size
+ * of image that can be created (size depends on width, height,
+ * and depth). For example, Windows 95, 98, and ME do not allow
+ * images larger than 16M.
+ * </p>
+ *
+ * @param device the device on which to create the image
+ * @param bounds a rectangle specifying the image's width and height (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the bounds rectangle is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, Rectangle bounds) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, bounds.width, bounds.height);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class from the given
+ * <code>ImageData</code>.
+ *
+ * @param device the device on which to create the image
+ * @param data the image data to create the image from (must not be null)
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the image data is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the depth of the ImageData is not supported</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, ImageData data) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, data);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class, whose type is
+ * <code>SWT.ICON</code>, from the two given <code>ImageData</code>
+ * objects. The two images must be the same size. Pixel transparency
+ * in either image will be ignored.
+ * <p>
+ * The mask image should contain white wherever the icon is to be visible,
+ * and black wherever the icon is to be transparent. In addition,
+ * the source image should contain black wherever the icon is to be
+ * transparent.
+ * </p>
+ *
+ * @param device the device on which to create the icon
+ * @param source the color data for the icon
+ * @param mask the mask data for the icon
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if either the source or mask is null </li>
+ * <li>ERROR_INVALID_ARGUMENT - if source and mask are different sizes</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image(Device device, ImageData source, ImageData mask) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (source == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (mask == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (source.width != mask.width || source.height != mask.height) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ mask = ImageData.convertMask (mask);
+ ImageData image = new ImageData(source.width, source.height, source.depth, source.palette, source.scanlinePad, source.data);
+ image.maskPad = mask.scanlinePad;
+ image.maskData = mask.data;
+ init(device, image);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the specified input stream. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type. Application code is still responsible
+ * for closing the input stream.
+ * <p>
+ * This constructor is provided for convenience when loading a single
+ * image only. If the stream contains multiple images, only the first
+ * one will be loaded. To load multiple images, use
+ * <code>ImageLoader.load()</code>.
+ * </p><p>
+ * This constructor may be used to load a resource as follows:
+ * </p>
+ * <pre>
+ * static Image loadImage (Display display, Class clazz, String string) {
+ * InputStream stream = clazz.getResourceAsStream (string);
+ * if (stream == null) return null;
+ * Image image = null;
+ * try {
+ * image = new Image (display, stream);
+ * } catch (SWTException ex) {
+ * } finally {
+ * try {
+ * stream.close ();
+ * } catch (IOException ex) {}
+ * }
+ * return image;
+ * }
+ * </pre>
+ *
+ * @param device the device on which to create the image
+ * @param stream the input stream to load the image from
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the stream is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_IO - if an IO error occurs while reading from the stream</li>
+ * <li>ERROR_INVALID_IMAGE - if the image stream contains invalid data </li>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the image stream describes an image with an unsupported depth</li>
+ * <li>ERROR_UNSUPPORTED_FORMAT - if the image stream contains an unrecognized format</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image (Device device, InputStream stream) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ init(device, new ImageData(stream));
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs an instance of this class by loading its representation
+ * from the file with the specified name. Throws an error if an error
+ * occurs while loading the image, or if the result is an image
+ * of an unsupported type.
+ * <p>
+ * This constructor is provided for convenience when loading
+ * a single image only. If the specified file contains
+ * multiple images, only the first one will be used.
+ *
+ * @param device the device on which to create the image
+ * @param filename the name of the file to load the image from
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * <li>ERROR_NULL_ARGUMENT - if the file name is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_IO - if an IO error occurs while reading from the file</li>
+ * <li>ERROR_INVALID_IMAGE - if the image file contains invalid data </li>
+ * <li>ERROR_UNSUPPORTED_DEPTH - if the image file describes an image with an unsupported depth</li>
+ * <li>ERROR_UNSUPPORTED_FORMAT - if the image file contains an unrecognized format</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for image creation</li>
+ * </ul>
+ */
+public Image (Device device, String filename) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ try {
+ handle = OS.gcnew_BitmapImage();
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int length = filename.length();
+ char[] chars = new char[length + 1];
+ filename.getChars(0, length, chars, 0);
+ int str = OS.gcnew_String(chars);
+ if (str == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int uri = OS.gcnew_Uri(str, OS.UriKind_RelativeOrAbsolute);
+ if (uri == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.BitmapImage_BeginInit(handle);
+ OS.BitmapImage_CreateOptions(handle, OS.BitmapCreateOptions_PreservePixelFormat);
+ OS.BitmapImage_UriSource(handle, uri);
+ OS.BitmapImage_EndInit(handle);
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+ OS.GCHandle_Free(uri);
+ OS.GCHandle_Free(str);
+ return;
+ } catch (SWTException e) {}
+ init(device, new ImageData(filename));
+ if(device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the image. Applications must dispose of all images which
+ * they allocate.
+ */
+public void dispose () {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ if (memGC != null) memGC.dispose();
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ memGC = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * 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
+ */
+public boolean equals (Object object) {
+ if (object == this) return true;
+ if (!(object instanceof Image)) return false;
+ Image image = (Image) object;
+ return device == image.device && handle == image.handle;
+}
+
+/**
+ * Returns the color to which to map the transparent pixel, or null if
+ * the receiver has no transparent pixel.
+ * <p>
+ * There are certain uses of Images that do not support transparency
+ * (for example, setting an image into a button or label). In these cases,
+ * it may be desired to simulate transparency by using the background
+ * color of the widget to paint the transparent pixels of the image.
+ * Use this method to check which color will be used in these cases
+ * in place of transparency. This value may be set with setBackground().
+ * <p>
+ *
+ * @return the background color of the image, or null if there is no transparency in the image
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Color getBackground() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (transparentPixel == -1) return null;
+ //TODO implement Image.getBackground()
+ return null;
+}
+
+/**
+ * Returns the bounds of the receiver. The rectangle will always
+ * have x and y values of 0, and the width and height of the
+ * image.
+ *
+ * @return a rectangle specifying the image's bounds
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
+ * </ul>
+ */
+public Rectangle getBounds() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width == -1 || height == -1) {
+ width = OS.BitmapSource_PixelWidth(handle);
+ height = OS.BitmapSource_PixelHeight(handle);
+ }
+ return new Rectangle(0, 0, width, height);
+}
+
+Point getDPI () {
+ //TODO
+ return new Point (96, 96);
+}
+
+/**
+ * Returns an <code>ImageData</code> based on the receiver
+ * Modifications made to this <code>ImageData</code> will not
+ * affect the Image.
+ *
+ * @return an <code>ImageData</code> containing the image's data and attributes
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_INVALID_IMAGE - if the image is not a bitmap or an icon</li>
+ * </ul>
+ *
+ * @see ImageData
+ */
+public ImageData getImageData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int format = OS.BitmapSource_Format(handle);
+ int depth = OS.PixelFormat_BitsPerPixel(format);
+ int width = OS.BitmapSource_PixelWidth(handle);
+ int height = OS.BitmapSource_PixelHeight(handle);
+ int scanlinePad = DEFAULT_SCANLINE_PAD;
+ int bytesPerLine = (((width * depth + 7) / 8) + (scanlinePad - 1)) / scanlinePad * scanlinePad;
+ byte[] buffer = new byte[bytesPerLine * height];
+ int rect = OS.Int32Rect_Empty();
+ OS.BitmapSource_CopyPixels(handle, rect, buffer, buffer.length, bytesPerLine);
+ OS.GCHandle_Free(rect);
+ PaletteData paletteData = null;
+ int palette = OS.BitmapSource_Palette(handle);
+ if (palette != 0) {
+ int colors = OS.BitmapPalette_Colors(palette);
+ int count = OS.ColorList_Count(colors);
+ RGB[] rgbs = new RGB[count];
+ paletteData = new PaletteData(rgbs);
+ if (count != 0) {
+ int index = 0;
+ int enumerator = OS.ColorList_GetEnumerator(colors);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int color = OS.ColorList_Current(enumerator);
+ rgbs[index++] = new RGB(OS.Color_R(color) & 0xFF, OS.Color_G(color) & 0xFF, OS.Color_B(color) & 0xFF);
+ OS.GCHandle_Free(color);
+ }
+ OS.GCHandle_Free(enumerator);
+ }
+ OS.GCHandle_Free(colors);
+ OS.GCHandle_Free(palette);
+ } else {
+ int[] formats = {
+ OS.PixelFormats_Bgr555(),
+ OS.PixelFormats_Bgr565(),
+ OS.PixelFormats_Bgr24(),
+ OS.PixelFormats_Rgb24(),
+ OS.PixelFormats_Bgr32(),
+ OS.PixelFormats_Bgra32(),
+ OS.PixelFormats_Pbgra32(),
+ OS.PixelFormats_Bgr101010(),
+ };
+ for (int i = 0; i < formats.length; i++) {
+ if (OS.Object_Equals(format, formats[i])) {
+ switch (i) {
+ case 0: paletteData = new PaletteData(0x7C00, 0x3E0, 0x1F); break;
+ case 1: paletteData = new PaletteData(0xF800, 0x7E0, 0x1F); break;
+ case 2: paletteData = new PaletteData(0xFF, 0xFF00, 0xFF0000); break;
+ case 3: paletteData = new PaletteData(0xFF0000, 0xFF00, 0xFF); break;
+ case 4:
+ case 5:
+ case 6: paletteData = new PaletteData(0xFF00, 0xFF0000, 0xFF000000); break;
+ case 7: paletteData = new PaletteData(0x3FF, 0xFFC00, 0x3FF0000); break;
+ }
+ }
+ OS.GCHandle_Free(formats[i]);
+ }
+ }
+ OS.GCHandle_Free(format);
+ ImageData data = new ImageData(width, height, depth, paletteData, scanlinePad, buffer);
+ data.transparentPixel = transparentPixel;
+ if (transparentPixel == -1 && type == SWT.ICON) {
+ /* Get the icon mask data */
+ int maskPad = 2;
+ int maskBpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad;
+ byte[] maskData = new byte[height * maskBpl];
+ int offset = 3, maskOffset = 0;
+ for (int y = 0; y<height; y++) {
+ for (int x = 0; x<width; x++) {
+ if (buffer[offset] != 0) {
+ maskData[maskOffset + (x >> 3)] |= (1 << (7 - (x & 0x7)));
+ } else {
+ maskData[maskOffset + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
+ }
+ offset += 4;
+ }
+ maskOffset += maskBpl;
+ }
+ data.maskData = maskData;
+ data.maskPad = maskPad;
+ }
+ data.alpha = alpha;
+ if (alpha == -1 && alphaData != null) {
+ data.alphaData = new byte[alphaData.length];
+ System.arraycopy(alphaData, 0, data.alphaData, 0, alphaData.length);
+ }
+ return data;
+}
+
+/**
+ * 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
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+void init(Device device, int width, int height) {
+ if (width <= 0 || height <= 0) {
+ SWT.error (SWT.ERROR_INVALID_ARGUMENT);
+ }
+ this.device = device;
+ type = SWT.BITMAP;
+ Point dpi = getDPI();
+ int pixelFormat = OS.PixelFormats_Bgr24();
+ int stride = width * 3;
+ byte[] buffer = new byte[stride * height];
+ for (int i = 0; i < buffer.length; i++) {
+ buffer[i] = (byte)0xFF;
+ }
+ handle = OS.BitmapSource_Create(width, height, dpi.x, dpi.y, pixelFormat, 0, buffer, buffer.length, stride);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(pixelFormat);
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+}
+
+void init(Device device, ImageData data) {
+ PaletteData palette = data.palette;
+ if (!(((data.depth == 1 || data.depth == 2 || data.depth == 4 || data.depth == 8) && !palette.isDirect) ||
+ ((data.depth == 8) || (data.depth == 16 || data.depth == 24 || data.depth == 32) && palette.isDirect)))
+ SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
+ this.device = device;
+ int width = data.width;
+ int height = data.height;
+ int redMask = palette.redMask;
+ int greenMask = palette.greenMask;
+ int blueMask = palette.blueMask;
+ ImageData newData = null;
+ int pixelFormat = 0;
+ boolean transparent = false;
+ if (data.maskData != null) {
+ transparent= true;
+ } else {
+ if (data.transparentPixel != -1) {
+ transparent = palette.isDirect;
+ } else {
+ if (data.alpha != -1) {
+ transparent = palette.isDirect;
+ } else {
+ transparent = data.alphaData != null;
+ }
+ }
+ }
+ if (transparent) {
+ pixelFormat = OS.PixelFormats_Bgra32();
+ if (!(palette.isDirect && data.depth == 32 && redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000)) {
+ newData = new ImageData(width, height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ } else {
+ switch (data.depth) {
+ case 1: pixelFormat = OS.PixelFormats_Indexed1(); break;
+ case 2: pixelFormat = OS.PixelFormats_Indexed2(); break;
+ case 4: pixelFormat = OS.PixelFormats_Indexed4(); break;
+ case 8:
+ if (!palette.isDirect) {
+ pixelFormat = OS.PixelFormats_Indexed8();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr32();
+ newData = new ImageData(data.width, data.height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ break;
+ case 16:
+ if (redMask == 0x7C00 && greenMask == 0x3E0 && blueMask == 0x1F) {
+ pixelFormat = OS.PixelFormats_Bgr555();
+ } else if (redMask == 0xF800 && greenMask == 0x7E0 && blueMask == 0x1F) {
+ pixelFormat = OS.PixelFormats_Bgr565();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr555();
+ newData = new ImageData(data.width, data.height, 16, new PaletteData(0x7C00, 0x3E0, 0x1F));
+ }
+ break;
+ case 24:
+ if (redMask == 0xFF && greenMask == 0xFF00 && blueMask == 0xFF0000) {
+ pixelFormat = OS.PixelFormats_Bgr24();
+ } else if (redMask == 0xFF0000 && greenMask == 0xFF00 && blueMask == 0xFF) {
+ pixelFormat = OS.PixelFormats_Rgb24();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr24();
+ newData = new ImageData(data.width, data.height, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000));
+ }
+ break;
+ case 32:
+ if (redMask == 0x3FF && greenMask == 0xFFC00 && blueMask == 0x3FF0000) {
+ pixelFormat = OS.PixelFormats_Bgr101010();
+ } else if (redMask == 0xFF00 && greenMask == 0xFF0000 && blueMask == 0xFF000000) {
+ pixelFormat = OS.PixelFormats_Bgr32();
+ } else {
+ pixelFormat = OS.PixelFormats_Bgr32();
+ newData = new ImageData(data.width, data.height, 32, new PaletteData(0xFF00, 0xFF0000, 0xFF000000));
+ }
+ break;
+ }
+ }
+ if (newData != null) {
+ PaletteData newPalette = newData.palette;
+ if (palette.isDirect) {
+ ImageData.blit(ImageData.BLIT_SRC,
+ data.data, data.depth, data.bytesPerLine, data.getByteOrder(), 0, 0, width, height, redMask, greenMask, blueMask,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ } else {
+ RGB[] rgbs = palette.getRGBs();
+ int length = rgbs.length;
+ byte[] srcReds = new byte[length];
+ byte[] srcGreens = new byte[length];
+ byte[] srcBlues = new byte[length];
+ for (int i = 0; i < rgbs.length; i++) {
+ RGB rgb = rgbs[i];
+ if (rgb == null) continue;
+ srcReds[i] = (byte)rgb.red;
+ srcGreens[i] = (byte)rgb.green;
+ srcBlues[i] = (byte)rgb.blue;
+ }
+ ImageData.blit(ImageData.BLIT_SRC,
+ data.data, data.depth, data.bytesPerLine, data.getByteOrder(), 0, 0, width, height, srcReds, srcGreens, srcBlues,
+ ImageData.ALPHA_OPAQUE, null, 0, 0, 0,
+ newData.data, newData.depth, newData.bytesPerLine, newData.getByteOrder(), 0, 0, width, height, newPalette.redMask, newPalette.greenMask, newPalette.blueMask,
+ false, false);
+ }
+ if (data.transparentPixel != -1) {
+ newData.transparentPixel = newPalette.getPixel(palette.getRGB(data.transparentPixel));
+ }
+ newData.maskPad = data.maskPad;
+ newData.maskData = data.maskData;
+ newData.alpha = data.alpha;
+ newData.alphaData = data.alphaData;
+ data = newData;
+ palette = data.palette;
+ }
+ int bitmapPalette = 0;
+ if (!palette.isDirect) {
+ if (data.transparentPixel != -1) {
+ transparentPixel = data.transparentPixel;
+ } else {
+ alpha = data.alpha;
+ }
+ RGB[] rgbs = palette.colors;
+ int list = OS.gcnew_ColorList(rgbs.length);
+ for (int i = 0; i < rgbs.length; i++) {
+ RGB rgb = rgbs[i];
+ byte alpha;
+ if (data.transparentPixel != -1) {
+ alpha = (byte)(i == data.transparentPixel ? 0 : 0xFF);
+ } else {
+ alpha = (byte)(data.alpha & 0xFF);
+ }
+ int color = OS.Color_FromArgb(alpha, (byte)rgb.red, (byte)rgb.green, (byte)rgb.blue);
+ OS.ColorList_Add(list, color);
+ OS.GCHandle_Free(color);
+ }
+ bitmapPalette = OS.gcnew_BitmapPalette(list);
+ OS.GCHandle_Free(list);
+ }
+ type = SWT.BITMAP;
+ if (transparent) {
+ if (data.maskData != null || data.transparentPixel != -1) {
+ this.type = data.transparentPixel != -1 ? SWT.BITMAP : SWT.ICON;
+ transparentPixel = data.transparentPixel;
+ ImageData maskImage = data.getTransparencyMask();
+ byte[] maskData = maskImage.data;
+ int maskBpl = maskImage.bytesPerLine;
+ int offset = 3, maskOffset = 0;
+ for (int y = 0; y<height; y++) {
+ for (int x = 0; x<width; x++) {
+ data.data[offset] = ((maskData[maskOffset + (x >> 3)]) & (1 << (7 - (x & 0x7)))) != 0 ? (byte)0xff : 0;
+ offset += 4;
+ }
+ maskOffset += maskBpl;
+ }
+ } else if (data.alpha != -1) {
+ alpha = data.alpha;
+ for (int i = 3, j = 0; i < data.data.length; i+=4, j++) {
+ data.data[i] = (byte)alpha;
+ }
+ } else {
+ int length = data.alphaData.length;
+ alphaData = new byte[length];
+ System.arraycopy(data.alphaData, 0, alphaData, 0, length);
+ for (int i = 3, j = 0; i < data.data.length; i+=4, j++) {
+ data.data[i] = alphaData[j];
+ }
+ }
+ }
+ Point dpi = getDPI();
+ handle = OS.BitmapSource_Create(width, height, dpi.x, dpi.y, pixelFormat, bitmapPalette, data.data, data.data.length, data.bytesPerLine);
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+ OS.GCHandle_Free(pixelFormat);
+ if (bitmapPalette != 0) OS.GCHandle_Free(bitmapPalette);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</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 data the platform specific GC data
+ * @return the platform specific GC handle
+ */
+public int internal_new_GC (GCData data) {
+ if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ /*
+ * Create a new GC that can draw into the image.
+ * Only supported for bitmaps.
+ */
+ if (type != SWT.BITMAP || memGC != null) {
+ SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ }
+ if (width == -1 || height == -1) {
+ width = OS.BitmapSource_PixelWidth(handle);
+ height = OS.BitmapSource_PixelHeight(handle);
+ }
+
+ int visual = OS.gcnew_DrawingVisual();
+ if (visual == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ int rect = OS.gcnew_Rect(0, 0, width, height);
+ int geometry = OS.gcnew_RectangleGeometry(rect);
+ OS.ContainerVisual_Clip (visual, geometry);
+ int dc = OS.DrawingVisual_RenderOpen(visual);
+ if (dc == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ Point dpi = getDPI();
+ int pixelFormat = OS.PixelFormats_Pbgra32();
+ int renderHandle = OS.gcnew_RenderTargetBitmap(width, height, dpi.x, dpi.y, pixelFormat);
+ if (renderHandle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.DrawingContext_DrawImage(dc, handle, rect);
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry);
+ if (data != null) {
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ if ((data.style & mask) == 0) {
+ data.style |= SWT.LEFT_TO_RIGHT;
+ }
+ data.device = device;
+ data.image = this;
+ data.background = OS.Colors_White;
+ data.foreground = OS.Colors_Black;
+ data.font = device.systemFont;
+ data.visual = visual;
+ data.renderHandle = renderHandle;
+ }
+ return dc;
+}
+
+/**
+ * Invokes platform specific functionality to dispose a GC handle.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</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 dc the platform specific GC handle
+ * @param data the platform specific GC data
+ */
+public void internal_dispose_GC (int dc, GCData data) {
+ OS.DrawingContext_Close(dc);
+ int renderHandle = data.renderHandle;
+ OS.RenderTargetBitmap_Render(renderHandle, data.visual);
+ OS.GCHandle_Free(data.visual);
+ OS.GCHandle_Free(dc);
+ int format = OS.BitmapSource_Format(handle);
+ int palette = OS.BitmapSource_Palette(handle);
+ OS.GCHandle_Free(handle);
+ handle = OS.gcnew_FormatConvertedBitmap(renderHandle, format, palette, 100);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GCHandle_Free(renderHandle);
+ renderHandle = 0;
+ if (OS.Freezable_CanFreeze(handle)) OS.Freezable_Freeze(handle);
+}
+
+/**
+ * Returns <code>true</code> if the image has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the image.
+ * When an image has been disposed, it is an error to
+ * invoke any other method using the image.
+ *
+ * @return <code>true</code> when the image is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Sets the color to which to map the transparent pixel.
+ * <p>
+ * There are certain uses of <code>Images</code> that do not support
+ * transparency (for example, setting an image into a button or label).
+ * In these cases, it may be desired to simulate transparency by using
+ * the background color of the widget to paint the transparent pixels
+ * of the image. This method specifies the color that will be used in
+ * these cases. For example:
+ * <pre>
+ * Button b = new Button();
+ * image.setBackground(b.getBackground());
+ * b.setImage(image);
+ * </pre>
+ * </p><p>
+ * The image may be modified by this operation (in effect, the
+ * transparent regions may be filled with the supplied color). Hence
+ * this operation is not reversible and it is not legal to call
+ * this function twice or with a null argument.
+ * </p><p>
+ * This method has no effect if the receiver does not have a transparent
+ * pixel value.
+ * </p>
+ *
+ * @param color the color to use when a transparent pixel is specified
+ *
+ * @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>
+ */
+public void setBackground(Color color) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (color == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (transparentPixel == -1) return;
+ //TODO implement Image.setBackground()
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Image {*DISPOSED*}";
+ return "Image {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new image.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Image</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 device the device on which to allocate the color
+ * @param type the type of the image (<code>SWT.BITMAP</code> or <code>SWT.ICON</code>)
+ * @param handle the OS handle for the image
+ * @return a new image object containing the specified device, type and handle
+ */
+public static Image wpf_new(Device device, int type, int handle) {
+ if (device == null) device = Device.getDevice();
+ Image image = new Image();
+ image.type = type;
+ image.handle = handle;
+ image.device = device;
+ return image;
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java
new file mode 100644
index 0000000000..79c022a24e
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Path.java
@@ -0,0 +1,578 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class represent paths through the two-dimensional
+ * coordinate system. Paths do not have to be continuous, and can be
+ * described using lines, rectangles, arcs, cubic or quadratic bezier curves,
+ * glyphs, or other paths.
+ * <p>
+ * Application code must explicitly invoke the <code>Path.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @since 3.1
+ */
+public class Path extends Resource {
+
+ /**
+ * the OS resource for the Path
+ * (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;
+
+ int currentFigure, currentPoint;
+
+/**
+ * Constructs a new empty Path.
+ *
+ * @param device the device on which to allocate the path
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the path could not be obtained/li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Path (Device device) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ handle = OS.gcnew_PathGeometry();
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Adds to the receiver a circular or elliptical arc that lies within
+ * the specified rectangular area.
+ * <p>
+ * The resulting arc begins at <code>startAngle</code> and extends
+ * for <code>arcAngle</code> degrees.
+ * 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
+ * @param y the y coordinate of the upper-left corner of the arc
+ * @param width the width of the arc
+ * @param height the height of the arc
+ * @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>
+ */
+public void addArc(float x, float y, float width, float height, float startAngle, float arcAngle) {
+ if (isDisposed()) 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;
+ boolean isNegative = arcAngle < 0;
+ boolean isLargeAngle = arcAngle > 180 || arcAngle < -180;
+ arcAngle = arcAngle + startAngle;
+ if (isNegative) {
+ // swap angles
+ float tmp = startAngle;
+ startAngle = arcAngle;
+ arcAngle = tmp;
+ }
+ double x1 = Math.cos(startAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y1 = -1 * Math.sin(startAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ double x2 = Math.cos(arcAngle * Math.PI / 180) * width/2.0 + x + width/2.0;
+ double y2 = -1 * Math.sin(arcAngle * Math.PI / 180) * height/2.0 + y + height/2.0;
+ if (currentFigure == 0) {
+ currentFigure = OS.gcnew_PathFigure();
+ int figures = OS.PathGeometry_Figures(handle);
+ OS.PathFigureCollection_Add(figures, currentFigure);
+ OS.GCHandle_Free(figures);
+ }
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endPoint = OS.gcnew_Point(x2, y2);
+ int size = OS.gcnew_Size(width / 2.0, height / 2.0);
+ int arc = OS.gcnew_ArcSegment(endPoint, size, 0, isLargeAngle, OS.SweepDirection_Clockwise, true);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ if (OS.PathSegmentCollection_Count(segments) != 0) {
+ int segment = OS.gcnew_LineSegment(startPoint, true);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segment);
+ } else {
+ OS.PathFigure_StartPoint(currentFigure, startPoint);
+ }
+ OS.PathSegmentCollection_Add(segments, arc);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(arc);
+ OS.GCHandle_Free(size);
+ OS.GCHandle_Free(startPoint);
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = endPoint;
+ if (arcAngle > 360 || arcAngle < -360) {
+ OS.GCHandle_Free(currentFigure);
+ currentFigure = 0;
+ }
+
+}
+
+/**
+ * Adds to the receiver the path described by the parameter.
+ *
+ * @param path the path to add to the receiver
+ *
+ * @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>
+ */
+public void addPath(Path path) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ OS.PathGeometry_AddGeometry(handle, path.handle);
+ if (path.currentPoint != 0) {
+ currentPoint = OS.gcnew_Point(OS.Point_X(path.currentPoint), OS.Point_Y(path.currentPoint));
+ }
+ int figures = OS.PathGeometry_Figures(handle);
+ int count = OS.PathFigureCollection_Count(figures);
+ OS.GCHandle_Free(figures);
+ if (count != 0) {
+ int figure = OS.PathGeometry_Figures(handle, count - 1);
+ if (!OS.PathFigure_IsClosed(figure)) {
+ currentFigure = figure;
+ return;
+ }
+ OS.GCHandle_Free(figure);
+ }
+
+}
+
+/**
+ * Adds to the receiver the rectangle specified by x, y, width and height.
+ *
+ * @param x the x coordinate of the rectangle to add
+ * @param y the y coordinate of the rectangle to add
+ * @param width the width of the rectangle to add
+ * @param height the height of the rectangle to add
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void addRectangle(float x, float y, float width, float height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry = OS.gcnew_RectangleGeometry(rect);
+ OS.PathGeometry_AddGeometry(handle, geometry);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(rect);
+ if (currentFigure != 0) OS.GCHandle_Free(currentFigure);
+ currentFigure = 0;
+ int point = OS.gcnew_Point(x, y);
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+
+}
+
+/**
+ * Adds to the receiver the pattern of glyphs generated by drawing
+ * the given string using the given font starting at the point (x, y).
+ *
+ * @param string the text to use
+ * @param x the x coordinate of the starting point
+ * @param y the y coordinate of the starting point
+ * @param font the font to use
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the font is null</li>
+ * <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>
+ */
+public void addString(String string, float x, float y, Font font) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (font == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int length = string.length();
+ char [] buffer = new char [length + 1];
+ string.getChars (0, length, buffer, 0);
+ int str = OS.gcnew_String (buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ int point = OS.gcnew_Point(x, y);
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, OS.FlowDirection_LeftToRight, font.handle, font.size, brush);
+ int geometry = OS.FormattedText_BuildGeometry(text, point);
+ OS.PathGeometry_AddGeometry(handle, geometry);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(point);
+ OS.GCHandle_Free(text);
+ if (currentFigure != 0) OS.GCHandle_Free(currentFigure);
+ currentFigure = 0;
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = 0;
+}
+
+/**
+ * Closes the current sub path by adding to the receiver a line
+ * from the current point of the path back to the starting point
+ * of the sub path.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void close() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (currentFigure != 0) OS.PathFigure_IsClosed(currentFigure, true);
+ currentFigure = 0;
+}
+
+/**
+ * Returns <code>true</code> if the specified point is contained by
+ * the receiver and false otherwise.
+ * <p>
+ * If outline is <code>true</code>, the point (x, y) checked for containment in
+ * the receiver's outline. If outline is <code>false</code>, the point is
+ * checked to see if it is contained within the bounds of the (closed) area
+ * covered by the receiver.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @param gc the GC to use when testing for containment
+ * @param outline controls whether to check the outline or contained area of the path
+ * @return <code>true</code> if the path contains the point and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the gc has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean contains(float x, float y, GC gc, boolean outline) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ gc.checkGC(GC.LINE_CAP | GC.LINE_JOIN | GC.LINE_STYLE | GC.LINE_WIDTH | GC.TRANSFORM);
+ boolean result;
+ int point = OS.gcnew_Point(x, y);
+ if (outline) {
+ result = OS.Geometry_StrokeContains(handle, gc.data.pen, point);
+ } else {
+ result = OS.Geometry_FillContains(handle, point);
+ }
+ OS.GCHandle_Free(point);
+ return result;
+}
+
+/**
+ * Adds to the receiver a cubic bezier curve based on the parameters.
+ *
+ * @param cx1 the x coordinate of the first control point of the spline
+ * @param cy1 the y coordinate of the first control of the spline
+ * @param cx2 the x coordinate of the second control of the spline
+ * @param cy2 the y coordinate of the second control of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void cubicTo(float cx1, float cy1, float cx2, float cy2, float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int controlPoint1 = OS.gcnew_Point(cx1, cy1);
+ int controlPoint2 = OS.gcnew_Point(cx2, cy2);
+ int point = OS.gcnew_Point(x, y);
+ if (currentFigure == 0) newFigure();
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ int segment = OS.gcnew_BezierSegment(controlPoint1, controlPoint2, point, true);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(segment);
+ OS.GCHandle_Free(controlPoint1);
+ OS.GCHandle_Free(controlPoint2);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the Path. Applications must dispose of all Paths that
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Replaces the first four elements in the parameter with values that
+ * describe the smallest rectangle that will completely contain the
+ * receiver (i.e. the bounding box).
+ *
+ * @param bounds the array to hold the result
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the bounding box</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getBounds(float[] bounds) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (bounds == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (bounds.length < 4) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.PathGeometry_Bounds(handle);
+ bounds[0] = (float)OS.Rect_X(rect);
+ bounds[1] = (float)OS.Rect_Y(rect);
+ bounds[2] = (float)OS.Rect_Width(rect);
+ bounds[3] = (float)OS.Rect_Height(rect);
+ OS.GCHandle_Free(rect);
+}
+
+/**
+ * Replaces the first two elements in the parameter with values that
+ * describe the current point of the path.
+ *
+ * @param point the array to hold the result
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the end point</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void getCurrentPoint(float[] point) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (point == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (point.length < 2) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (currentPoint != 0) {
+ point[0] = (float)OS.Point_X(currentPoint);
+ point[1] = (float)OS.Point_Y(currentPoint);
+ } else {
+ point[0] = point[1] = 0;
+ }
+}
+
+/**
+ * Returns a device independent representation of the receiver.
+ *
+ * @return the PathData for the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see PathData
+ */
+public PathData getPathData() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ byte[] types = new byte[128];
+ float[] points = new float[128 * 2];
+ int pointsIndex = 0, typesIndex = 0;
+ int figures = OS.PathGeometry_Figures(handle);
+ int figureCount = OS.PathFigureCollection_Count(figures);
+ OS.GCHandle_Free(figures);
+ for (int i = 0; i < figureCount; i++) {
+ int figure = OS.PathGeometry_Figures(handle, i);
+ int segments = OS.PathFigure_Segments(figure);
+ int segmentCount = OS.PathSegmentCollection_Count(segments);
+ OS.GCHandle_Free(segments);
+ for (int j = 0; j < segmentCount; j++) {
+ int segment = OS.PathFigure_Segments(figure, j);
+ int type = OS.Object_GetType(segment);
+ //TODO - need get points out of every segment
+ //TODO - need to convert ArcSegment to beziers
+
+
+ OS.GCHandle_Free(type);
+ OS.GCHandle_Free(segment);
+ }
+ OS.GCHandle_Free(figure);
+ }
+ if (typesIndex != types.length) {
+ byte[] newTypes = new byte[typesIndex];
+ System.arraycopy(types, 0, newTypes, 0, typesIndex);
+ types = newTypes;
+ }
+ if (pointsIndex != points.length) {
+ float[] newPoints = new float[pointsIndex];
+ System.arraycopy(points, 0, newPoints, 0, pointsIndex);
+ points = newPoints;
+ }
+ PathData result = new PathData();
+ result.types = types;
+ result.points = points;
+ return result;
+}
+
+/**
+ * Adds to the receiver a line from the current point to
+ * the point specified by (x, y).
+ *
+ * @param x the x coordinate of the end of the line to add
+ * @param y the y coordinate of the end of the line to add
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void lineTo(float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int point = OS.gcnew_Point(x, y);
+ if (currentFigure == 0) newFigure();
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ int segment = OS.gcnew_LineSegment(point, true);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(segment);
+}
+
+/**
+ * Returns <code>true</code> if the Path has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Path.
+ * When a Path has been disposed, it is an error to
+ * invoke any other method using the Path.
+ *
+ * @return <code>true</code> when the Path is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Sets the current point of the receiver to the point
+ * specified by (x, y). Note that this starts a new
+ * sub path.
+ *
+ * @param x the x coordinate of the new end point
+ * @param y the y coordinate of the new end point
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void moveTo(float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int point = OS.gcnew_Point(x, y);
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ if (currentFigure != 0) {
+ int segments = OS.PathFigure_Segments(currentFigure);
+ int count = OS.PathSegmentCollection_Count(segments);
+ OS.GCHandle_Free(segments);
+ if (count == 0) {
+ OS.PathFigure_StartPoint(currentFigure, point);
+ return;
+ }
+ }
+ if (currentFigure != 0) OS.GCHandle_Free(currentFigure);
+ newFigure();
+}
+
+void newFigure() {
+ currentFigure = OS.gcnew_PathFigure();
+ if (currentPoint != 0) {
+ OS.PathFigure_StartPoint(currentFigure, currentPoint);
+ }
+ int figures = OS.PathGeometry_Figures(handle);
+ OS.PathFigureCollection_Add(figures, currentFigure);
+ OS.GCHandle_Free(figures);
+}
+
+/**
+ * Adds to the receiver a quadratic curve based on the parameters.
+ *
+ * @param cx the x coordinate of the control point of the spline
+ * @param cy the y coordinate of the control point of the spline
+ * @param x the x coordinate of the end point of the spline
+ * @param y the y coordinate of the end point of the spline
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void quadTo(float cx, float cy, float x, float y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int controlPoint = OS.gcnew_Point(cx, cy);
+ int point = OS.gcnew_Point(x, y);
+ if (currentFigure == 0) newFigure();
+ if (currentPoint != 0) OS.GCHandle_Free(currentPoint);
+ currentPoint = point;
+ int segment = OS.gcnew_QuadraticBezierSegment(controlPoint, point, true);
+ int segments = OS.PathFigure_Segments(currentFigure);
+ OS.PathSegmentCollection_Add(segments, segment);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(segment);
+ OS.GCHandle_Free(controlPoint);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Path {*DISPOSED*}";
+ return "Path {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java
new file mode 100644
index 0000000000..845d177724
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Pattern.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class represent patterns to use while drawing. Patterns
+ * can be specified either as bitmaps or gradients.
+ * <p>
+ * Application code must explicitly invoke the <code>Pattern.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @since 3.1
+ */
+public class Pattern extends Resource {
+
+ /**
+ * the OS resource for the Pattern
+ * (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;
+
+/**
+ * Constructs a new Pattern given an image. Drawing with the resulting
+ * pattern will cause the image to be tiled over the resulting area.
+ *
+ * @param device the device on which to allocate the pattern
+ * @param image the image that the pattern will draw
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device, or the image is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Pattern(Device device, Image image) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.device = device;
+ handle = OS.gcnew_ImageBrush(image.handle);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.TileBrush_TileMode(handle, OS.TileMode_Tile);
+ OS.TileBrush_Stretch(handle, OS.Stretch_None);
+ OS.TileBrush_ViewportUnits(handle, OS.BrushMappingMode_Absolute);
+ OS.TileBrush_AlignmentX(handle, OS.AlignmentX_Left);
+ OS.TileBrush_AlignmentY(handle, OS.AlignmentY_Top);
+ int rect = OS.gcnew_Rect(0, 0, OS.BitmapSource_PixelWidth(image.handle), OS.BitmapSource_PixelHeight(image.handle));
+ OS.TileBrush_Viewport(handle, rect);
+ OS.GCHandle_Free(rect);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ *
+ * @param device the device on which to allocate the pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param color2 the ending color of the gradient
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ * or if either color1 or color2 is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, Color color2) {
+ this(device, x1, y1, x2, y2, color1, 0xFF, color2, 0xFF);
+}
+
+/**
+ * Constructs a new Pattern that represents a linear, two color
+ * gradient. Drawing with the pattern will cause the resulting area to be
+ * tiled with the gradient specified by the arguments.
+ *
+ * @param device the device on which to allocate the pattern
+ * @param x1 the x coordinate of the starting corner of the gradient
+ * @param y1 the y coordinate of the starting corner of the gradient
+ * @param x2 the x coordinate of the ending corner of the gradient
+ * @param y2 the y coordinate of the ending corner of the gradient
+ * @param color1 the starting color of the gradient
+ * @param alpha1 the starting alpha value of the gradient
+ * @param color2 the ending color of the gradient
+ * @param alpha2 the ending alpha value of the gradient
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device,
+ * or if either color1 or color2 is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if either color1 or color2 has been disposed</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the pattern could not be obtained/li>
+ * </ul>
+ *
+ * @see #dispose()
+ *
+ * @since 3.2
+ */
+public Pattern(Device device, float x1, float y1, float x2, float y2, Color color1, int alpha1, Color color2, int alpha2) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color1 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color1.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (color2 == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (color2.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ this.device = device;
+ int startColor = OS.Color_FromArgb((byte)(alpha1 & 0xFF), OS.Color_R(color1.handle), OS.Color_G(color1.handle), OS.Color_B(color1.handle));
+ int endColor = OS.Color_FromArgb((byte)(alpha2 & 0xFF), OS.Color_R(color2.handle), OS.Color_G(color2.handle), OS.Color_B(color2.handle));
+ int startPoint = OS.gcnew_Point(x1, y1);
+ int endPoint = OS.gcnew_Point(x2, y2);
+ handle = OS.gcnew_LinearGradientBrush(startColor, endColor, startPoint, endPoint);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ OS.GradientBrush_MappingMode(handle, OS.BrushMappingMode_Absolute);
+ OS.GradientBrush_SpreadMethod(handle, OS.GradientSpreadMethod_Repeat);
+ OS.GCHandle_Free(startColor);
+ OS.GCHandle_Free(endColor);
+ OS.GCHandle_Free(startPoint);
+ OS.GCHandle_Free(endPoint);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the Pattern. Applications must dispose of all Patterns that
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Returns <code>true</code> if the Pattern has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Pattern.
+ * When a Pattern has been disposed, it is an error to
+ * invoke any other method using the Pattern.
+ *
+ * @return <code>true</code> when the Pattern is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Pattern {*DISPOSED*}";
+ return "Pattern {" + handle + "}";
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java
new file mode 100644
index 0000000000..c009aa81b8
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Region.java
@@ -0,0 +1,720 @@
+/*******************************************************************************
+ * 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.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * Instances of this class represent areas of an x-y coordinate
+ * system that are aggregates of the areas covered by a number
+ * of polygons.
+ * <p>
+ * Application code must explicitly invoke the <code>Region.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ */
+
+public final class Region extends Resource {
+
+ /**
+ * the OS resource for the region
+ * (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;
+
+/**
+ * Constructs a new empty region.
+ *
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for region creation</li>
+ * </ul>
+ */
+public Region () {
+ this(null);
+}
+
+/**
+ * Constructs a new empty region.
+ * <p>
+ * You must dispose the region when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the region
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle could not be obtained for region creation</li>
+ * </ul>
+ *
+ * @see #dispose
+ *
+ * @since 3.0
+ */
+public Region (Device device) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ handle = OS.gcnew_GeometryGroup();
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (device.tracking) device.new_Object(this);
+}
+
+/**
+ * Constructs a new region given a handle to the operating
+ * system resources that it should represent.
+ *
+ * @param handle the handle for the result
+ */
+Region(Device device, int handle) {
+ this.device = device;
+ this.handle = handle;
+}
+
+/**
+ * Adds the given polygon to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+*
+ */
+public void add (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ combine(pointArray, OS.GeometryCombineMode_Union);
+}
+
+
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void add (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ add (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Adds the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void add (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry1 = OS.gcnew_RectangleGeometry(rect);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) == 0) {
+ OS.GeometryCollection_Add(geometries, geometry1);
+ } else {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Union, geometry1, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry1);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Adds all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to merge
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void add (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) == 0) {
+ OS.GeometryCollection_Add(geometries, region.handle);
+ } else {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Union, region.handle, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+}
+
+
+void combine (int[] pointArray, int mode) {
+ if (pointArray.length < 4) return;
+ int list = OS.gcnew_PointCollection(pointArray.length / 2);
+ for (int i = 0; i < pointArray.length; i += 2) {
+ int point = OS.gcnew_Point(pointArray[i], pointArray[i + 1]);
+ OS.PointCollection_Add(list, point);
+ OS.GCHandle_Free(point);
+ }
+ int poly = OS.gcnew_PolyLineSegment(list, true);
+ OS.GCHandle_Free(list);
+ int figure = OS.gcnew_PathFigure();
+ int startPoint = OS.gcnew_Point(pointArray[0], pointArray[1]);
+ OS.PathFigure_StartPoint(figure, startPoint);
+ OS.PathFigure_IsClosed(figure, true);
+ int segments = OS.PathFigure_Segments(figure);
+ OS.PathSegmentCollection_Add(segments, poly);
+ int path = OS.gcnew_PathGeometry();
+ int figures = OS.PathGeometry_Figures(path);
+ OS.PathFigureCollection_Add(figures, figure);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) == 0) {
+ if (mode == OS.GeometryCombineMode_Union) OS.GeometryCollection_Add(geometries, path);
+ } else {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(mode, geometry2, path);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+ OS.GCHandle_Free(figures);
+ OS.GCHandle_Free(path);
+ OS.GCHandle_Free(segments);
+ OS.GCHandle_Free(figure);
+ OS.GCHandle_Free(startPoint);
+ OS.GCHandle_Free(poly);
+}
+
+/**
+ * Returns <code>true</code> if the point specified by the
+ * arguments is inside the area specified by the receiver,
+ * and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the point to test for containment
+ * @param y the y coordinate of the point to test for containment
+ * @return <code>true</code> if the region contains the point and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean contains (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int point = OS.gcnew_Point(x, y);
+ boolean result = OS.Geometry_FillContains(handle, point);
+ OS.GCHandle_Free(point);
+ return result;
+}
+
+/**
+ * Returns <code>true</code> if the given point is inside the
+ * area specified by the receiver, and <code>false</code>
+ * otherwise.
+ *
+ * @param pt the point to test for containment
+ * @return <code>true</code> if the region contains the point and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean contains (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return contains(pt.x, pt.y);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the region. Applications must dispose of all regions which
+ * they allocate.
+ */
+public void dispose () {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * 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
+ */
+public boolean equals (Object object) {
+ if (this == object) return true;
+ if (!(object instanceof Region)) return false;
+ Region rgn = (Region)object;
+ return handle == rgn.handle;
+}
+
+/**
+ * Returns a rectangle which represents the rectangular
+ * union of the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @return a bounding rectangle for the region
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#union
+ */
+public Rectangle getBounds() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (OS.Geometry_IsEmpty(handle)) return new Rectangle(0, 0, 0, 0);
+ int rect = OS.Geometry_Bounds(handle);
+ Rectangle result = new Rectangle((int)OS.Rect_X(rect), (int)OS.Rect_Y(rect), (int)OS.Rect_Width(rect), (int)OS.Rect_Height(rect));
+ OS.GCHandle_Free(rect);
+ return result;
+}
+
+/**
+ * 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
+ *
+ * @see #equals
+ */
+public int hashCode () {
+ return handle;
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to intersect with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void intersect (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ intersect (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Intersects the given rectangle to the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void intersect (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry1 = OS.gcnew_RectangleGeometry(rect);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Intersect, geometry1, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry1);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Intersects all of the polygons which make up the area covered
+ * by the argument to the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to intersect
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void intersect (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Intersect, region.handle, geometry2);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Returns <code>true</code> if the rectangle described by the
+ * arguments intersects with any of the polygons the receiver
+ * maintains to describe its area, and <code>false</code> otherwise.
+ *
+ * @param x the x coordinate of the origin of the rectangle
+ * @param y the y coordinate of the origin of the rectangle
+ * @param width the width of the rectangle
+ * @param height the height of the rectangle
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public boolean intersects (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry = OS.gcnew_RectangleGeometry(rect);
+ int result = OS.Geometry_FillContainsWithDetail(handle, geometry);
+ OS.GCHandle_Free(geometry);
+ OS.GCHandle_Free(rect);
+ return result != OS.IntersectionDetail_Empty;
+}
+
+/**
+ * Returns <code>true</code> if the given rectangle intersects
+ * with any of the polygons the receiver maintains to describe
+ * its area and <code>false</code> otherwise.
+ *
+ * @param rect the rectangle to test for intersection
+ * @return <code>true</code> if the rectangle intersects with the receiver, and <code>false</code> otherwise
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see Rectangle#intersects(Rectangle)
+ */
+public boolean intersects (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ return intersects(rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Returns <code>true</code> if the region has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the region.
+ * When a region has been disposed, it is an error to
+ * invoke any other method using the region.
+ *
+ * @return <code>true</code> when the region is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns <code>true</code> if the receiver does not cover any
+ * area in the (x, y) coordinate plane, and <code>false</code> if
+ * the receiver does cover some area in the plane.
+ *
+ * @return <code>true</code> if the receiver is empty, and <code>false</code> otherwise
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public boolean isEmpty () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Geometry_IsEmpty(handle);
+}
+
+/**
+ * Subtracts the given polygon from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param pointArray points that describe the polygon to merge with the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (int[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ combine(pointArray, OS.GeometryCombineMode_Exclude);
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param rect the rectangle to subtract from the receiver
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (Rectangle rect) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ subtract (rect.x, rect.y, rect.width, rect.height);
+}
+
+/**
+ * Subtracts the given rectangle from the collection of polygons
+ * the receiver maintains to describe its area.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param width the width coordinate of the rectangle
+ * @param height the height coordinate of the rectangle
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the rectangle's width or height is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void subtract (int x, int y, int width, int height) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (width < 0 || height < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int rect = OS.gcnew_Rect(x, y, width, height);
+ int geometry1 = OS.gcnew_RectangleGeometry(rect);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Exclude, geometry2, geometry1);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(rect);
+ OS.GCHandle_Free(geometry1);
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Subtracts all of the polygons which make up the area covered
+ * by the argument from the collection of polygons the receiver
+ * maintains to describe its area.
+ *
+ * @param region the region to subtract
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the argument has been disposed</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.0
+ */
+public void subtract (Region region) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (region == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (region.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int geometries = OS.GeometryGroup_Children(handle);
+ if (OS.GeometryCollection_Count(geometries) != 0) {
+ int geometry2 = OS.GeometryGroup_Children(handle, 0);
+ int geometry3 = OS.gcnew_CombinedGeometry(OS.GeometryCombineMode_Exclude, geometry2, region.handle);
+ OS.GeometryCollection_Remove(geometries, geometry2);
+ OS.GeometryCollection_Add(geometries, geometry3);
+ OS.GCHandle_Free(geometry2);
+ OS.GCHandle_Free(geometry3);
+ }
+ OS.GCHandle_Free(geometries);
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param x the x coordinate of the point to translate
+ * @param y the y coordinate of the point to translate
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void translate (int x, int y) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ int transform1 = OS.Geometry_Transform(handle);
+ int transform2 = OS.gcnew_TranslateTransform(x, y);
+ int transform = OS.gcnew_TransformGroup();
+ int transforms = OS.TransformGroup_Children(transform);
+ OS.TransformCollection_Add(transforms, transform1);
+ OS.TransformCollection_Add(transforms, transform2);
+ OS.Geometry_Transform(handle, transform);
+ OS.GCHandle_Free(transform1);
+ OS.GCHandle_Free(transform2);
+ OS.GCHandle_Free(transform);
+ OS.GCHandle_Free(transforms);
+}
+
+/**
+ * Translate all of the polygons the receiver maintains to describe
+ * its area by the specified point.
+ *
+ * @param pt the point to translate
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.1
+ */
+public void translate (Point pt) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pt == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ translate (pt.x, pt.y);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "Region {*DISPOSED*}";
+ return "Region {" + handle + "}";
+}
+
+/**
+ * Invokes platform specific functionality to allocate a new region.
+ * <p>
+ * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
+ * API for <code>Region</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 device the device on which to allocate the region
+ * @param handle the handle for the region
+ * @return a new region object containing the specified device and handle
+ */
+public static Region wpf_new(Device device, int handle) {
+ return new Region(device, handle);
+}
+
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java
new file mode 100644
index 0000000000..68c313812b
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/TextLayout.java
@@ -0,0 +1,1658 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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.wpf.*;
+import org.eclipse.swt.*;
+
+/**
+ * <code>TextLayout</code> is a graphic object that represents
+ * styled text.
+ * <p>
+ * Instances of this class provide support for drawing, cursor
+ * navigation, hit testing, text wrapping, alignment, tab expansion
+ * line breaking, etc. These are aspects required for rendering internationalized text.
+ * </p><p>
+ * Application code must explicitly invoke the <code>TextLayout#dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @since 3.0
+ */
+public final class TextLayout extends Resource {
+ Font font;
+ String text, segmentsText;
+ int lineSpacing;
+ int ascent, descent;
+ int alignment;
+ int wrapWidth;
+ int orientation;
+ int indent;
+ boolean justify;
+ int[] tabs;
+ int[] segments;
+ StyleItem[] styles;
+
+ int string, defaultTextProperties;
+ int[] runs;
+ int[] lines;
+
+ static final char LTR_MARK = '\u200E', RTL_MARK = '\u200F';
+ static final int TAB_COUNT = 32;
+
+class StyleItem {
+ TextStyle style;
+ int start, length;
+ int textProperties;
+
+ void free() {
+ if (textProperties != 0) OS.GCHandle_Free(textProperties);
+ textProperties = 0;
+ }
+ public String toString () {
+ return "StyleItem {" + start + ", " + style + "}";
+ }
+}
+
+/**
+ * Constructs a new instance of this class on the given device.
+ * <p>
+ * You must dispose the text layout when it is no longer required.
+ * </p>
+ *
+ * @param device the device on which to allocate the text layout
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public TextLayout (Device device) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ wrapWidth = ascent = descent = -1;
+ lineSpacing = 0;
+ orientation = SWT.LEFT_TO_RIGHT;
+ styles = new StyleItem[2];
+ styles[0] = new StyleItem();
+ styles[1] = new StyleItem();
+ text = ""; //$NON-NLS-1$
+ if (device.tracking) device.new_Object(this);
+}
+
+void checkLayout () {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+}
+
+/*
+* Compute the runs: itemize, shape, place, and reorder the runs.
+* Break paragraphs into lines, wraps the text, and initialize caches.
+*/
+void computeRuns () {
+ if (lines != null) return;
+
+ int jniRef = OS.NewGlobalRef(this);
+ int textSource = OS.gcnew_SWTTextSource(jniRef);
+ int formatter = OS.TextFormatter_Create();
+ Font font = this.font != null ? this.font : device.systemFont;
+ segmentsText = getSegmentsText();
+ int length = segmentsText.length();
+ char [] buffer = new char [length + 1];
+ segmentsText.getChars (0, length, buffer, 0);
+ string = OS.gcnew_String(buffer);
+ int culture = OS.CultureInfo_CurrentUICulture();
+ defaultTextProperties = OS.gcnew_SWTTextRunProperties(font.handle, font.size, font.size, 0, 0, 0, OS.BaselineAlignment_Baseline, culture);
+ for (int i = 0; i < styles.length; i++) {
+ StyleItem run = styles[i];
+ TextStyle style = run.style;
+ if (style != null) {
+ Font styleFont = style.font != null ? style.font : font;
+ int fg = 0;
+ if (style.foreground != null) {
+ fg = OS.gcnew_SolidColorBrush(style.foreground.handle);
+ }
+ int bg = 0;
+ if (style.background != null) {
+ bg = OS.gcnew_SolidColorBrush(style.background.handle);
+ }
+ int decorations = 0;
+ if (style.strikeout || style.underline) {
+ decorations = OS.gcnew_TextDecorationCollection(2);
+ if (style.strikeout) {
+ int strikeout = OS.TextDecorations_Strikethrough();
+ OS.TextDecorationCollection_Add(decorations, strikeout);
+ OS.GCHandle_Free(strikeout);
+ }
+ if (style.underline) {
+ int underline = OS.TextDecorations_Underline();
+ OS.TextDecorationCollection_Add(decorations, underline);
+ OS.GCHandle_Free(underline);
+ }
+ }
+ run.textProperties = OS.gcnew_SWTTextRunProperties(styleFont.handle, styleFont.size, styleFont.size, decorations, fg, bg, OS.BaselineAlignment_Baseline, culture);
+ if (fg != 0) OS.GCHandle_Free(fg);
+ if (bg != 0) OS.GCHandle_Free(bg);
+ if (decorations != 0) OS.GCHandle_Free(decorations);
+ }
+ }
+ int textAlignment = OS.TextAlignment_Left;
+ if (justify) {
+ textAlignment = OS.TextAlignment_Justify;
+ } else {
+ switch (alignment) {
+ case SWT.CENTER: textAlignment = OS.TextAlignment_Center; break;
+ case SWT.RIGHT: textAlignment = OS.TextAlignment_Right; break;
+ }
+ }
+ int flowDirection = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int textWrapping = wrapWidth != -1 ? OS.TextWrapping_Wrap : OS.TextWrapping_NoWrap;
+ int tabCollection = 0;
+ if (tabs != null) {
+ int position = 0;
+ int tabLength = Math.max(tabs.length, TAB_COUNT), i;
+ tabCollection = OS.gcnew_TextTabPropertiesCollection(tabLength);
+ for (i = 0; i < tabs.length; i++) {
+ position = tabs[i];
+ int tab = OS.gcnew_TextTabProperties(OS.TextTabAlignment_Left, position, 0, 0);
+ OS.TextTabPropertiesCollection_Add(tabCollection, tab);
+ OS.GCHandle_Free(tab);
+ }
+ int width = tabs[tabs.length - 1];
+ if (tabs.length > 1) width -= tabs[tabs.length - 2];
+ if (width > 0) {
+ for (; i < length; i++) {
+ position += width;
+ int tab = OS.gcnew_TextTabProperties(OS.TextTabAlignment_Left, position, 0, 0);
+ OS.TextTabPropertiesCollection_Add(tabCollection, tab);
+ OS.GCHandle_Free(tab);
+ }
+ }
+ }
+ int paragraphProperties = OS.gcnew_SWTTextParagraphProperties(flowDirection, textAlignment, false, defaultTextProperties, textWrapping, 0, 0, tabCollection);
+ int firstParagraphProperties = OS.gcnew_SWTTextParagraphProperties(flowDirection, textAlignment, true, defaultTextProperties, textWrapping, 0, indent, tabCollection);
+ int offset = 0;
+ int index = 0;
+ lines = new int[4];
+ int lineBreak = 0;
+ while (offset < length || offset == 0) {
+ char ch;
+ boolean firstLine = offset == 0 || (ch = segmentsText.charAt(offset - 1)) == '\r' || ch == '\n';
+ int paragraphProps = firstLine ? firstParagraphProperties : paragraphProperties;
+ int textLine = OS.TextFormatter_FormatLine(formatter, textSource, offset, wrapWidth != -1 ? wrapWidth : 0, paragraphProps, lineBreak);
+ offset += OS.TextLine_Length(textLine);
+ lineBreak = OS.TextLine_GetTextLineBreak(textLine);
+ if (index == lines.length) {
+ int[] tmpLines = new int[index + 4];
+ System.arraycopy(lines, 0, tmpLines, 0, index);
+ lines = tmpLines;
+ }
+ lines[index++] = textLine;
+ }
+ if (index != lines.length) {
+ int[] tmpLines = new int[index];
+ System.arraycopy(lines, 0, tmpLines, 0, index);
+ lines = tmpLines;
+ }
+ if (tabCollection != 0) OS.GCHandle_Free(tabCollection);
+ OS.GCHandle_Free(paragraphProperties);
+ OS.GCHandle_Free(firstParagraphProperties);
+ OS.GCHandle_Free(culture);
+ OS.GCHandle_Free(formatter);
+ OS.GCHandle_Free(textSource);
+ OS.DeleteGlobalRef(jniRef);
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the text layout. Applications must dispose of all allocated text layouts.
+ */
+public void dispose () {
+ if (device == null) return;
+ freeRuns();
+ font = null;
+ text = null;
+ segmentsText = null;
+ tabs = null;
+ styles = null;
+// lineOffset = null;
+// lineY = null;
+// lineWidth = null;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ *
+ * @param gc the GC to draw
+ * @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 SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ */
+public void draw (GC gc, int x, int y) {
+ draw(gc, x, y, -1, -1, null, null);
+}
+
+/**
+ * Draws the receiver's text using the specified GC at the specified
+ * point.
+ *
+ * @param gc the GC to draw
+ * @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 selectionStart the offset where the selections starts, or -1 indicating no selection
+ * @param selectionEnd the offset where the selections ends, or -1 indicating no selection
+ * @param selectionForeground selection foreground, or NULL to use the system default color
+ * @param selectionBackground selection background, or NULL to use the system default color
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the gc is null</li>
+ * </ul>
+ */
+public void draw (GC gc, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) {
+ checkLayout();
+ computeRuns();
+ if (gc == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (gc.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionForeground != null && selectionForeground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (selectionBackground != null && selectionBackground.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int length = text.length();
+ if (length == 0) return;
+ gc.checkGC(GC.FOREGROUND);
+ int fg = OS.Pen_Brush(gc.data.pen);
+ OS.SWTTextRunProperties_ForegroundBrush(defaultTextProperties, fg);
+ for (int i = 0; i < styles.length; i++) {
+ StyleItem run = styles[i];
+ if (run.style != null && run.style.foreground == null) {
+ OS.SWTTextRunProperties_ForegroundBrush(run.textProperties, fg);
+ }
+ }
+ int drawingContext = gc.handle;
+ boolean hasSelection = selectionStart <= selectionEnd && selectionStart != -1 && selectionEnd != -1;
+ int selBrush = 0;
+ if (hasSelection) {
+ selectionStart = Math.min(Math.max(0, selectionStart), length - 1);
+ selectionEnd = Math.min(Math.max(0, selectionEnd), length - 1);
+ selectionStart = translateOffset(selectionStart);
+ selectionEnd = translateOffset(selectionEnd);
+ if (selectionBackground != null) {
+ selBrush = OS.gcnew_SolidColorBrush(selectionBackground.handle);
+ } else {
+ selBrush = OS.Brushes_LightSkyBlue();
+ }
+ }
+ int lineStart = 0, lineEnd = 0;
+ double drawY = y;
+ for (int i = 0; i < lines.length; i++) {
+ int line = lines[i];
+ if (line == 0) break;
+ lineStart = lineEnd;
+ lineEnd = lineStart + OS.TextLine_Length(line);
+ double nextDrawY;
+ int lineHeight = (int)OS.TextLine_Height(line);
+ if (ascent != -1 && descent != -1) {
+ lineHeight = Math.max(lineHeight, ascent + descent);
+ nextDrawY = drawY + lineHeight + lineSpacing;
+ int baseline = (int)OS.TextLine_Baseline(line);
+ if (ascent > baseline) drawY += ascent - baseline;
+ } else {
+ nextDrawY = drawY + lineHeight + lineSpacing;
+ }
+
+ //draw line selection
+ boolean fullSelection = selectionStart <= lineStart && selectionEnd >= lineEnd;
+ boolean partialSelection = !(selectionStart > lineEnd || lineStart > selectionEnd);
+ if (hasSelection && (fullSelection || partialSelection)) {
+ int selLineStart = Math.max (lineStart, selectionStart);
+ int selLineEnd = Math.min (lineEnd, selectionEnd);
+ int rects = OS.TextLine_GetTextBounds(line, selLineStart, selLineEnd - selLineStart + 1);
+ if (rects != 0) {
+ int enumerator = OS.TextBoundsCollection_GetEnumerator(rects);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int bounds = OS.TextBoundsCollection_Current(enumerator);
+ int textRect = OS.TextBounds_Rectangle(bounds);
+ OS.Rect_Y(textRect, OS.Rect_Y(textRect) + drawY);
+ OS.DrawingContext_DrawRectangle(drawingContext, selBrush, 0, textRect);
+ OS.GCHandle_Free(textRect);
+ OS.GCHandle_Free(bounds);
+ }
+ OS.GCHandle_Free(enumerator);
+ }
+ OS.GCHandle_Free(rects);
+ }
+
+ //draw line text
+ int point = OS.gcnew_Point(x, drawY);
+ OS.TextLine_Draw(line, drawingContext, point, 0);
+ OS.GCHandle_Free(point);
+
+ drawY = nextDrawY;
+ }
+ if (selBrush != 0) OS.GCHandle_Free(selBrush);
+ OS.GCHandle_Free(fg);
+}
+
+void freeRuns () {
+ if (lines == null) return;
+ for (int i = 0; i < lines.length; i++) {
+ if (lines[i] != 0) {
+ OS.GCHandle_Free(lines[i]);
+ }
+ }
+ lines = null;
+ if (runs != null) {
+ for (int i = 0; i < runs.length; i++) {
+ if (runs[i] == 0) break;
+ OS.GCHandle_Free(runs[i]);
+ }
+ runs = null;
+ }
+ for (int i = 0; i < styles.length; i++) {
+ styles[i].free();
+ }
+ if (defaultTextProperties != 0) OS.GCHandle_Free(defaultTextProperties);
+ if (string != 0) OS.GCHandle_Free(string);
+ defaultTextProperties = string = 0;
+ segmentsText = null;
+}
+
+/**
+ * Returns the receiver's horizontal text alignment, which will be one
+ * of <code>SWT.LEFT</code>, <code>SWT.CENTER</code> or
+ * <code>SWT.RIGHT</code>.
+ *
+ * @return the alignment used to positioned text horizontally
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getAlignment () {
+ checkLayout();
+ return alignment;
+}
+
+/**
+ * Returns the ascent of the receiver.
+ *
+ * @return the ascent
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getDescent()
+ * @see #setDescent(int)
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getAscent () {
+ checkLayout();
+ return ascent;
+}
+
+/**
+ * Returns the bounds of the receiver.
+ *
+ * @return the bounds of the receiver
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getBounds () {
+ checkLayout();
+ computeRuns();
+ double width = 0;
+ double height = 0;
+ for (int line=0; line<lines.length; line++) {
+ if (wrapWidth == -1) width = Math.max(width, OS.TextLine_WidthIncludingTrailingWhitespace(lines[line]));
+ int lineHeight = (int)OS.TextLine_Height(lines[line]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ height += lineHeight + lineSpacing;
+ }
+ if (wrapWidth != -1) width = wrapWidth;
+ return new Rectangle (0, 0, (int)width, (int)height);
+}
+
+/**
+ * Returns the bounds for the specified range of characters. The
+ * bounds is the smallest rectangle that encompasses all characters
+ * in the range. The start and end offsets are inclusive and will be
+ * clamped if out of range.
+ *
+ * @param start the start offset
+ * @param end the end offset
+ * @return the bounds of the character range
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getBounds (int start, int end) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (length == 0) return new Rectangle(0, 0, 0, 0);
+ if (start > end) return new Rectangle(0, 0, 0, 0);
+ start = Math.min(Math.max(0, start), length - 1);
+ end = Math.min(Math.max(0, end), length - 1);
+ start = translateOffset(start);
+ end = translateOffset(end);
+ int lineStart = 0, lineEnd = 0, lineY = 0;
+ int rect = 0;
+ for (int i = 0; i < lines.length; i++) {
+ int lineLength = OS.TextLine_Length(lines[i]);
+ lineStart = lineEnd;
+ lineEnd = lineStart + lineLength;
+ if (start < lineEnd) {
+ if (end < lineStart) break;
+ int rangeStart = Math.max(start, lineStart);
+ int rangLength = Math.min(end, lineEnd) - rangeStart + 1;
+ int rects = OS.TextLine_GetTextBounds(lines[i], rangeStart, rangLength);
+ if (rects != 0) {
+ int enumerator = OS.TextBoundsCollection_GetEnumerator(rects);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int bounds = OS.TextBoundsCollection_Current(enumerator);
+ int textRect = OS.TextBounds_Rectangle(bounds);
+ OS.Rect_Y(textRect, OS.Rect_Y(textRect) + lineY);
+ if (rect != 0) {
+ OS.Rect_Union(rect, textRect);
+ OS.GCHandle_Free(textRect);
+ } else {
+ rect = textRect;
+ }
+ OS.GCHandle_Free(bounds);
+ }
+ OS.GCHandle_Free(enumerator);
+ }
+ OS.GCHandle_Free(rects);
+ }
+ int lineHeight = (int)OS.TextLine_Height(lines[i]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ lineY += lineHeight + lineSpacing;
+ }
+ if (rect == 0) return new Rectangle(0, 0, 0, 0);
+ Rectangle result = new Rectangle((int)OS.Rect_X(rect), (int)OS.Rect_Y(rect), (int)OS.Rect_Width(rect), (int)OS.Rect_Height(rect));
+ OS.GCHandle_Free(rect);
+ return result;
+}
+
+/**
+ * Returns the descent of the receiver.
+ *
+ * @return the descent
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getAscent()
+ * @see #setAscent(int)
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public int getDescent () {
+ checkLayout();
+ return descent;
+}
+
+/**
+ * Returns the default 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>
+ */
+public Font getFont () {
+ checkLayout();
+ return font;
+}
+
+/**
+* Returns the receiver's indent.
+*
+* @return the receiver's indent
+*
+* @exception SWTException <ul>
+* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+*
+* @since 3.2
+*/
+public int getIndent () {
+ checkLayout();
+ return indent;
+}
+
+/**
+* Returns the receiver's justification.
+*
+* @return the receiver's justification
+*
+* @exception SWTException <ul>
+* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+* </ul>
+*
+* @since 3.2
+*/
+public boolean getJustify () {
+ checkLayout();
+ return justify;
+}
+
+/**
+ * Returns the embedding level for the specified character offset. The
+ * embedding level is usually used to determine the directionality of a
+ * character in bidirectional text.
+ *
+ * @param offset the charecter offset
+ * @return the embedding level
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ */
+public int getLevel (int offset) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ offset = translateOffset(offset);
+ int level = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? 1 : 0;
+ for (int i = 0; i < lines.length; i++) {
+ int lineLength = OS.TextLine_Length(lines[i]);
+ if (lineLength > offset) {
+ int runs = OS.TextLine_GetIndexedGlyphRuns (lines[i]);
+ int enumerator = OS.IndexedGlyphRunCollection_GetEnumerator(runs);
+ while (OS.IEnumerator_MoveNext(enumerator)) {
+ int indexedGlyphRun = OS.IndexedGlyphRunCollection_Current(enumerator);
+ int rangeStart = OS.IndexedGlyphRun_TextSourceCharacterIndex(indexedGlyphRun);
+ int rangeEnd = rangeStart + OS.IndexedGlyphRun_TextSourceLength(indexedGlyphRun);
+ int glyphRun = OS.IndexedGlyphRun_GlyphRun(indexedGlyphRun);
+ int bidiLevel = OS.GlyphRun_BidiLevel(glyphRun);
+ OS.GCHandle_Free(glyphRun);
+ OS.GCHandle_Free(indexedGlyphRun);
+ if (rangeStart <= offset && offset < rangeEnd) {
+ level = bidiLevel;
+ break;
+ }
+ }
+ OS.GCHandle_Free(enumerator);
+ OS.GCHandle_Free(runs);
+ break;
+ }
+ }
+ return level;
+}
+
+/**
+ * Returns the bounds of the line for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the line bounds
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the line index is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public Rectangle getLineBounds(int lineIndex) {
+ checkLayout();
+ computeRuns();
+ if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ int offset = 0;
+ double y = 0;
+ for (int i=0; i<lineIndex; i++) {
+ offset += OS.TextLine_Length(lines[i]);
+ int lineHeight = (int)OS.TextLine_Height(lines[i]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ y += lineHeight + lineSpacing;
+ }
+ int line = lines[lineIndex];
+ double x = OS.TextLine_Start(line);
+ double width = OS.TextLine_Width(line);
+ double height = OS.TextLine_Height(line);
+ if (ascent != -1 && descent != -1) height = Math.max(height, ascent + descent);
+ char ch;
+ boolean firstLine = offset == 0 || (ch = segmentsText.charAt(offset - 1)) == '\r' || ch == '\n';
+ if (firstLine) {
+ x += indent;
+ width -= indent;
+ }
+ return new Rectangle ((int)x, (int)y, (int)width, (int)height);
+}
+
+/**
+ * Returns the receiver's line count. This includes lines caused
+ * by wrapping.
+ *
+ * @return the line count
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineCount () {
+ checkLayout();
+ computeRuns();
+ return lines.length;
+}
+
+/**
+ * Returns the index of the line that contains the specified
+ * character offset.
+ *
+ * @param offset the character offset
+ * @return the line index
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getLineIndex (int offset) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ offset = translateOffset(offset);
+ int start = 0;
+ for (int line=0; line<lines.length; line++) {
+ int lineLength = OS.TextLine_Length(lines[line]);
+ if (start + lineLength > offset) return line;
+ start += lineLength;
+ }
+ return lines.length - 1;
+}
+
+/**
+ * Returns the font metrics for the specified line index.
+ *
+ * @param lineIndex the line index
+ * @return the font metrics
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the line index is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public FontMetrics getLineMetrics (int lineIndex) {
+ checkLayout();
+ computeRuns();
+ if (!(0 <= lineIndex && lineIndex < runs.length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ int length = text.length();
+ double baseline, height;
+ if (length == 0) {
+ Font font = this.font != null ? this.font : device.systemFont;
+ int str = OS.gcnew_String (new char []{' ', '\0'});
+ int culture = OS.CultureInfo_CurrentUICulture();
+ int direction = (orientation & SWT.RIGHT_TO_LEFT) != 0 ? OS.FlowDirection_RightToLeft : OS.FlowDirection_LeftToRight;
+ int brush = OS.Brushes_White();
+ int text = OS.gcnew_FormattedText(str, culture, direction, font.handle, font.size, brush);
+ height = OS.FormattedText_Height(text);
+ baseline = OS.FormattedText_Baseline(text);
+ OS.GCHandle_Free(text);
+ OS.GCHandle_Free(str);
+ OS.GCHandle_Free(brush);
+ OS.GCHandle_Free(culture);
+ } else {
+ baseline = OS.TextLine_Baseline(lines[lineIndex]);
+ height = OS.TextLine_Height(lines[lineIndex]);
+ if (ascent != -1 && descent != -1) {
+ baseline = Math.max(baseline, ascent);
+ height = Math.max(height, ascent + descent);
+ }
+ }
+ return FontMetrics.wpf_new((int)baseline, (int)(height - baseline), 0, 0, (int)height);
+}
+
+/**
+ * Returns the line offsets. Each value in the array is the
+ * offset for the first character in a line except for the last
+ * value, which contains the length of the text.
+ *
+ * @return the line offsets
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getLineOffsets () {
+ checkLayout();
+ computeRuns();
+ int start = 0;
+ int[] offsets = new int[lines.length+1];
+ for (int i = 0; i < lines.length; i++) {
+ start += OS.TextLine_Length(lines[i]);
+ offsets[i+1] = untranslateOffset(start);
+ }
+ return offsets;
+}
+
+/**
+ * Returns the location for the specified character offset. The
+ * <code>trailing</code> argument indicates whether the offset
+ * corresponds to the leading or trailing edge of the cluster.
+ *
+ * @param offset the character offset
+ * @param trailing the trailing flag
+ * @return the location of the character offset
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getOffset(Point, int[])
+ * @see #getOffset(int, int, int[])
+ */
+public Point getLocation (int offset, boolean trailing) {
+ checkLayout();
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ length = segmentsText.length();
+ offset = translateOffset(offset);
+ double y = 0;
+ int start = 0, line;
+ for (line=0; line<lines.length; line++) {
+ int lineLength = OS.TextLine_Length(lines[line]);
+ if (start + lineLength > offset) break;
+ start += lineLength;
+ int lineHeight = (int)OS.TextLine_Height(lines[line]);
+ if (ascent != -1 && descent != -1) lineHeight = Math.max(lineHeight, ascent + descent);
+ y += lineHeight + lineSpacing;
+ }
+ int characterHit = OS.gcnew_CharacterHit(offset, trailing ? 1 : 0);
+ double x = OS.TextLine_GetDistanceFromCharacterHit(lines[line], characterHit);
+ OS.GCHandle_Free(characterHit);
+ return new Point((int)x, (int)y);
+}
+
+/**
+ * Returns the next offset for the specified offset and movement
+ * type. The movement is one of <code>SWT.MOVEMENT_CHAR</code>,
+ * <code>SWT.MOVEMENT_CLUSTER</code> or <code>SWT.MOVEMENT_WORD</code>.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the next offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getPreviousOffset(int, int)
+ */
+public int getNextOffset (int offset, int movement) {
+ checkLayout();
+ return _getOffset (offset, movement, true);
+}
+
+int _getOffset(int offset, int movement, boolean forward) {
+ computeRuns();
+ int length = text.length();
+ if (!(0 <= offset && offset <= length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ if (forward && offset == length) return length;
+ if (!forward && offset == 0) return 0;
+ int step = forward ? 1 : -1;
+ if ((movement & SWT.MOVEMENT_CHAR) != 0) return offset + step;
+ length = segmentsText.length();
+ offset = translateOffset(offset);
+ int lineStart = 0;
+ for (int line=0; line<lines.length; line++) {
+ int lineLength = OS.TextLine_Length(lines[line]);
+ if (lineStart <= offset && offset < lineStart + lineLength) {
+ if (forward) {
+ if (offset >= lineStart + lineLength - OS.TextLine_NewlineLength(lines[line])) {
+ return untranslateOffset(lineStart + lineLength);
+ }
+ } else {
+ if (offset == lineStart) {
+ if (line == 0) return 0;
+ int breakLength = OS.TextLine_NewlineLength(lines[line - 1]);
+ if (breakLength != 0) {
+ return untranslateOffset(offset - breakLength);
+ }
+ }
+ }
+ int resultCharHit;
+ int characterHit = OS.gcnew_CharacterHit(offset, 0);
+ if (forward) {
+ resultCharHit = OS.TextLine_GetNextCaretCharacterHit(lines[line], characterHit);
+ } else {
+ resultCharHit = OS.TextLine_GetPreviousCaretCharacterHit(lines[line], characterHit);
+ }
+ int result = OS.CharacterHit_FirstCharacterIndex(resultCharHit);
+ int trailing = OS.CharacterHit_TrailingLength(resultCharHit);
+ OS.GCHandle_Free(resultCharHit);
+ OS.GCHandle_Free(characterHit);
+ return untranslateOffset(result + trailing);
+ }
+ lineStart += lineLength;
+ }
+ return forward ? text.length() : 0;
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1). When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param point the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the trailing length is less than <code>1</code></li>
+ * <li>ERROR_NULL_ARGUMENT - if the point is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getLocation(int, boolean)
+ */
+public int getOffset (Point point, int[] trailing) {
+ checkLayout();
+ if (point == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
+ return getOffset (point.x, point.y, trailing) ;
+}
+
+/**
+ * Returns the character offset for the specified point.
+ * For a typical character, the trailing argument will be filled in to
+ * indicate whether the point is closer to the leading edge (0) or
+ * the trailing edge (1). When the point is over a cluster composed
+ * of multiple characters, the trailing argument will be filled with the
+ * position of the character in the cluster that is closest to
+ * the point.
+ *
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ * @param trailing the trailing buffer
+ * @return the character offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the trailing length is less than <code>1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getLocation(int, boolean)
+ */
+public int getOffset (int x, int y, int[] trailing) {
+ checkLayout();
+ computeRuns();
+ if (trailing != null && trailing.length < 1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ double lineY = 0;
+ int line;
+ for (line=0; line<lines.length; line++) {
+ double lineHeight = OS.TextLine_Length(lines[line]);
+ if (lineY + lineHeight > y) break;
+ lineY += lineHeight;
+ }
+ if (line >= lines.length) line = lines.length - 1;
+ int characterHit = OS.TextLine_GetCharacterHitFromDistance(lines[line], x);
+ int offset = OS.CharacterHit_FirstCharacterIndex(characterHit);
+ if (trailing != null) trailing[0] = OS.CharacterHit_TrailingLength(characterHit);
+ OS.GCHandle_Free(characterHit);
+ return untranslateOffset(offset);
+}
+
+/**
+ * Returns the orientation of the receiver.
+ *
+ * @return the orientation style
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getOrientation () {
+ checkLayout();
+ return orientation;
+}
+
+/**
+ * Returns the previous offset for the specified offset and movement
+ * type. The movement is one of <code>SWT.MOVEMENT_CHAR</code>,
+ * <code>SWT.MOVEMENT_CLUSTER</code> or <code>SWT.MOVEMENT_WORD</code>.
+ *
+ * @param offset the start offset
+ * @param movement the movement type
+ * @return the previous offset
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getNextOffset(int, int)
+ */
+public int getPreviousOffset (int offset, int movement) {
+ checkLayout();
+ return _getOffset (offset, movement, false);
+}
+
+/**
+ * Gets the ranges of text that are associated with a <code>TextStyle</code>.
+ *
+ * @return the ranges, an array of offsets representing the start and end of each
+ * text style.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getStyles()
+ *
+ * @since 3.2
+ */
+public int[] getRanges () {
+ checkLayout();
+ int[] result = new int[styles.length * 2];
+ int count = 0;
+ for (int i=0; i<styles.length - 1; i++) {
+ if (styles[i].style != null) {
+ result[count++] = styles[i].start;
+ result[count++] = styles[i + 1].start - 1;
+ }
+ }
+ if (count != result.length) {
+ int[] newResult = new int[count];
+ System.arraycopy(result, 0, newResult, 0, count);
+ result = newResult;
+ }
+ return result;
+}
+
+/**
+ * Returns the text segments offsets of the receiver.
+ *
+ * @return the text segments offsets
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getSegments () {
+ checkLayout();
+ return segments;
+}
+
+String getSegmentsText() {
+ if (segments == null) return text;
+ int nSegments = segments.length;
+ if (nSegments <= 1) return text;
+ int length = text.length();
+ if (length == 0) return text;
+ if (nSegments == 2) {
+ if (segments[0] == 0 && segments[1] == length) return text;
+ }
+ char[] oldChars = new char[length];
+ text.getChars(0, length, oldChars, 0);
+ char[] newChars = new char[length + nSegments];
+ int charCount = 0, segmentCount = 0;
+ char separator = orientation == SWT.RIGHT_TO_LEFT ? RTL_MARK : LTR_MARK;
+ while (charCount < length) {
+ if (segmentCount < nSegments && charCount == segments[segmentCount]) {
+ newChars[charCount + segmentCount++] = separator;
+ } else {
+ newChars[charCount + segmentCount] = oldChars[charCount++];
+ }
+ }
+ if (segmentCount < nSegments) {
+ segments[segmentCount] = charCount;
+ newChars[charCount + segmentCount++] = separator;
+ }
+ return new String(newChars, 0, Math.min(charCount + segmentCount, newChars.length));
+}
+
+/**
+ * Returns the line spacing of the receiver.
+ *
+ * @return the line spacing
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getSpacing () {
+ checkLayout();
+ return lineSpacing;
+}
+
+/**
+ * Gets the style of the receiver at the specified character offset.
+ *
+ * @param offset the text offset
+ * @return the style or <code>null</code> if not set
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the character offset is out of range</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public TextStyle getStyle (int offset) {
+ checkLayout();
+ int length = text.length();
+ if (!(0 <= offset && offset < length)) SWT.error(SWT.ERROR_INVALID_RANGE);
+ for (int i=1; i<styles.length; i++) {
+ if (styles[i].start > offset) {
+ return styles[i - 1].style;
+ }
+ }
+ return null;
+}
+
+/**
+ * Gets all styles of the receiver.
+ *
+ * @return the styles
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #getRanges()
+ *
+ * @since 3.2
+ */
+public TextStyle[] getStyles () {
+ checkLayout();
+ TextStyle[] result = new TextStyle[styles.length];
+ int count = 0;
+ for (int i=0; i<styles.length; i++) {
+ if (styles[i].style != null) {
+ result[count++] = styles[i].style;
+ }
+ }
+ if (count != result.length) {
+ TextStyle[] newResult = new TextStyle[count];
+ System.arraycopy(result, 0, newResult, 0, count);
+ result = newResult;
+ }
+ return result;
+}
+
+/**
+ * Returns the tab list of the receiver.
+ *
+ * @return the tab list
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int[] getTabs () {
+ checkLayout();
+ return tabs;
+}
+
+int GetTextRun(int textSourceCharacterIndex) {
+ if (runs == null) runs = new int[4];
+ int index = 0;
+ while (index < runs.length && runs[index] != 0) index++;
+ if (index == runs.length) {
+ int[] tmpRuns = new int[index + 4];
+ System.arraycopy(runs, 0, tmpRuns, 0, index);
+ runs = tmpRuns;
+ }
+ int length = OS.String_Length(string);
+ if (textSourceCharacterIndex >= length) {
+ runs[index] = OS.gcnew_TextEndOfParagraph(1, defaultTextProperties);
+ } else {
+ int styleIndex = 1;
+ while (styleIndex < styles.length && styles[styleIndex].start <= textSourceCharacterIndex) styleIndex++;
+ TextStyle textStyle = styles[styleIndex - 1].style;
+ int textProperties = styles[styleIndex - 1].textProperties;
+ if (textProperties == 0) textProperties = defaultTextProperties;
+ int end = styles[styleIndex].start;
+ if (textStyle != null && textStyle.metrics != null) {
+ GlyphMetrics metrics = textStyle.metrics;
+ runs[index] = OS.gcnew_SWTTextEmbeddedObject(textProperties, end - textSourceCharacterIndex, metrics.width, metrics.ascent + metrics.descent, metrics.ascent);
+ } else {
+ char ch = segmentsText.charAt(textSourceCharacterIndex);
+ if (ch == '\n' || ch == '\r') {
+ int breakLength = 1;
+ if (ch == '\r' && textSourceCharacterIndex + 1 < end && segmentsText.charAt(textSourceCharacterIndex + 1) == '\n') breakLength++;
+ runs[index] = OS.gcnew_TextEndOfLine(breakLength, textProperties);
+ } else {
+ int i = textSourceCharacterIndex;
+ while (i < end && (ch = segmentsText.charAt(i)) != '\n' && ch != '\r') i++;
+ runs[index] = OS.gcnew_TextCharacters(string, textSourceCharacterIndex, i - textSourceCharacterIndex, textProperties);
+ }
+ }
+ }
+ return runs[index];
+}
+
+int GetPrecedingText(int textSourceCharacterIndexLimit) {
+ System.out.println("GetPrecedingText");
+ return 0;
+}
+
+/**
+ * Gets the receiver's text, which will be an empty
+ * string if it has never been set.
+ *
+ * @return the receiver's text
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public String getText () {
+ checkLayout();
+ return text;
+}
+
+/**
+ * Returns the width of the receiver.
+ *
+ * @return the width
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public int getWidth () {
+ checkLayout();
+ return wrapWidth;
+}
+
+/**
+ * Returns <code>true</code> if the text layout has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the text layout.
+ * When a text layout has been disposed, it is an error to
+ * invoke any other method using the text layout.
+ * </p>
+ *
+ * @return <code>true</code> when the text layout is disposed and <code>false</code> otherwise
+ */
+public boolean isDisposed () {
+ return device == null;
+}
+
+/**
+ * Sets the text alignment for the receiver. The alignment controls
+ * how a line of text is positioned horizontally. The argument should
+ * be one of <code>SWT.LEFT</code>, <code>SWT.RIGHT</code> or <code>SWT.CENTER</code>.
+ * <p>
+ * The default alignment is <code>SWT.LEFT</code>. Note that the receiver's
+ * width must be set in order to use <code>SWT.RIGHT</code> or <code>SWT.CENTER</code>
+ * alignment.
+ * </p>
+ *
+ * @param alignment the new alignment
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setWidth(int)
+ */
+public void setAlignment (int alignment) {
+ checkLayout();
+ int mask = SWT.LEFT | SWT.CENTER | SWT.RIGHT;
+ alignment &= mask;
+ if (alignment == 0) return;
+ if ((alignment & SWT.LEFT) != 0) alignment = SWT.LEFT;
+ if ((alignment & SWT.RIGHT) != 0) alignment = SWT.RIGHT;
+ if (this.alignment == alignment) return;
+ freeRuns();
+ this.alignment = alignment;
+}
+
+/**
+ * Sets the ascent of the receiver. The ascent is distance in pixels
+ * from the baseline to the top of the line and it is applied to all
+ * lines. The default value is <code>-1</code> which means that the
+ * ascent is calculated from the line fonts.
+ *
+ * @param ascent the new ascent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the ascent is less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setDescent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setAscent(int ascent) {
+ checkLayout();
+ if (ascent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.ascent == ascent) return;
+ freeRuns();
+ this.ascent = ascent;
+}
+
+/**
+ * Sets the descent of the receiver. The descent is distance in pixels
+ * from the baseline to the bottom of the line and it is applied to all
+ * lines. The default value is <code>-1</code> which means that the
+ * descent is calculated from the line fonts.
+ *
+ * @param descent the new descent
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the descent is less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAscent(int)
+ * @see #getLineMetrics(int)
+ */
+public void setDescent(int descent) {
+ checkLayout();
+ if (descent < -1) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.descent == descent) return;
+ freeRuns();
+ this.descent = descent;
+}
+
+/**
+ * Sets the default font which will be used by the receiver
+ * to draw and measure text. If the
+ * argument is null, then a default font appropriate
+ * for the platform will be used instead. Note that a text
+ * style can override the default font.
+ *
+ * @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>
+ */
+public void setFont (Font font) {
+ checkLayout();
+ if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.font == font) return;
+ if (font != null && font.equals(this.font)) return;
+ freeRuns();
+ this.font = font;
+}
+
+/**
+ * Sets the indent of the receiver. This indent it applied of the first line of
+ * each paragraph.
+ *
+ * @param indent new indent
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setIndent (int indent) {
+ checkLayout();
+ if (indent < 0) return;
+ if (this.indent == indent) return;
+ freeRuns();
+ this.indent = indent;
+}
+
+/**
+ * Sets the justification of the receiver. Note that the receiver's
+ * width must be set in order to use justification.
+ *
+ * @param justify new justify
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @since 3.2
+ */
+public void setJustify (boolean justify) {
+ checkLayout();
+ if (this.justify == justify) return;
+ freeRuns();
+ this.justify = justify;
+}
+
+/**
+ * Sets the orientation of the receiver, which must be one
+ * of <code>SWT.LEFT_TO_RIGHT</code> or <code>SWT.RIGHT_TO_LEFT</code>.
+ *
+ * @param orientation new orientation style
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setOrientation (int orientation) {
+ checkLayout();
+ int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
+ orientation &= mask;
+ if (orientation == 0) return;
+ if ((orientation & SWT.LEFT_TO_RIGHT) != 0) orientation = SWT.LEFT_TO_RIGHT;
+ if (this.orientation == orientation) return;
+ this.orientation = orientation;
+ freeRuns();
+}
+
+/**
+ * Sets the offsets of the receiver's text segments. Text segments are used to
+ * override the default behaviour of the bidirectional algorithm.
+ * Bidirectional reordering can happen within a text segment but not
+ * between two adjacent segments.
+ * <p>
+ * Each text segment is determined by two consecutive offsets in the
+ * <code>segments</code> arrays. The first element of the array should
+ * always be zero and the last one should always be equals to length of
+ * the text.
+ * </p>
+ *
+ * @param segments the text segments offset
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setSegments(int[] segments) {
+ checkLayout();
+ if (this.segments == null && segments == null) return;
+ if (this.segments != null && segments != null) {
+ if (this.segments.length == segments.length) {
+ int i;
+ for (i = 0; i <segments.length; i++) {
+ if (this.segments[i] != segments[i]) break;
+ }
+ if (i == segments.length) return;
+ }
+ }
+ freeRuns();
+ this.segments = segments;
+}
+
+/**
+ * Sets the line spacing of the receiver. The line spacing
+ * is the space left between lines.
+ *
+ * @param spacing the new line spacing
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the spacing is negative</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setSpacing (int spacing) {
+ checkLayout();
+ if (spacing < 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.lineSpacing == spacing) return;
+ freeRuns();
+ this.lineSpacing = spacing;
+}
+
+/**
+ * Sets the style of the receiver for the specified range. Styles previously
+ * set for that range will be overwritten. The start and end offsets are
+ * inclusive and will be clamped if out of range.
+ *
+ * @param style the style
+ * @param start the start offset
+ * @param end the end offset
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setStyle (TextStyle style, int start, int end) {
+ checkLayout();
+ int length = text.length();
+ if (length == 0) return;
+ if (start > end) return;
+ start = Math.min(Math.max(0, start), length - 1);
+ end = Math.min(Math.max(0, end), length - 1);
+ int low = -1;
+ int high = styles.length;
+ while (high - low > 1) {
+ int index = (high + low) / 2;
+ if (styles[index + 1].start > start) {
+ high = index;
+ } else {
+ low = index;
+ }
+ }
+ if (0 <= high && high < styles.length) {
+ StyleItem item = styles[high];
+ if (item.start == start && styles[high + 1].start - 1 == end) {
+ if (style == null) {
+ if (item.style == null) return;
+ } else {
+ if (style.equals(item.style)) return;
+ }
+ }
+ }
+ freeRuns();
+ int modifyStart = high;
+ int modifyEnd = modifyStart;
+ while (modifyEnd < styles.length) {
+ if (styles[modifyEnd + 1].start > end) break;
+ modifyEnd++;
+ }
+ if (modifyStart == modifyEnd) {
+ int styleStart = styles[modifyStart].start;
+ int styleEnd = styles[modifyEnd + 1].start - 1;
+ if (styleStart == start && styleEnd == end) {
+ styles[modifyStart].style = style;
+ return;
+ }
+ if (styleStart != start && styleEnd != end) {
+ StyleItem[] newStyles = new StyleItem[styles.length + 2];
+ System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+ StyleItem item = new StyleItem();
+ item.start = start;
+ item.style = style;
+ newStyles[modifyStart + 1] = item;
+ item = new StyleItem();
+ item.start = end + 1;
+ item.style = styles[modifyStart].style;
+ newStyles[modifyStart + 2] = item;
+ System.arraycopy(styles, modifyEnd + 1, newStyles, modifyEnd + 3, styles.length - modifyEnd - 1);
+ styles = newStyles;
+ return;
+ }
+ }
+ if (start == styles[modifyStart].start) modifyStart--;
+ if (end == styles[modifyEnd + 1].start - 1) modifyEnd++;
+ int newLength = styles.length + 1 - (modifyEnd - modifyStart - 1);
+ StyleItem[] newStyles = new StyleItem[newLength];
+ System.arraycopy(styles, 0, newStyles, 0, modifyStart + 1);
+ StyleItem item = new StyleItem();
+ item.start = start;
+ item.style = style;
+ newStyles[modifyStart + 1] = item;
+ styles[modifyEnd].start = end + 1;
+ System.arraycopy(styles, modifyEnd, newStyles, modifyStart + 2, styles.length - modifyEnd);
+ styles = newStyles;
+}
+
+/**
+ * Sets the receiver's tab list. Each value in the tab list specifies
+ * the space in pixels from the origin of the text layout to the respective
+ * tab stop. The last tab stop width is repeated continuously.
+ *
+ * @param tabs the new tab list
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setTabs (int[] tabs) {
+ checkLayout();
+ if (this.tabs == null && tabs == null) return;
+ if (this.tabs != null && tabs !=null) {
+ if (this.tabs.length == tabs.length) {
+ int i;
+ for (i = 0; i <tabs.length; i++) {
+ if (this.tabs[i] != tabs[i]) break;
+ }
+ if (i == tabs.length) return;
+ }
+ }
+ freeRuns();
+ this.tabs = tabs;
+}
+
+/**
+ * Sets the receiver's text.
+ *
+ * @param text the new text
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the text is null</li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setText (String text) {
+ checkLayout();
+ if (text == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (text.equals(this.text)) return;
+ freeRuns();
+ this.text = text;
+ styles = new StyleItem[2];
+ styles[0] = new StyleItem();
+ styles[1] = new StyleItem();
+ styles[1].start = text.length();
+}
+
+/**
+ * Sets the line width of the receiver, which determines how
+ * text should be wrapped and aligned. The default value is
+ * <code>-1</code> which means wrapping is disabled.
+ *
+ * @param width the new width
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_INVALID_ARGUMENT - if the width is <code>0</code> or less than <code>-1</code></li>
+ * </ul>
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ *
+ * @see #setAlignment(int)
+ */
+public void setWidth (int width) {
+ checkLayout();
+ if (width < -1 || width == 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ if (this.wrapWidth == width) return;
+ freeRuns();
+ this.wrapWidth = width;
+}
+
+int validadeOffset(int offset, int step) {
+ offset += step;
+ if (segments != null && segments.length > 2) {
+ for (int i = 0; i < segments.length; i++) {
+ if (translateOffset(segments[i]) - 1 == offset) {
+ offset += step;
+ break;
+ }
+ }
+ }
+ return offset;
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString () {
+ if (isDisposed()) return "TextLayout {*DISPOSED*}";
+ return "TextLayout {}";
+}
+
+int translateOffset(int offset) {
+ if (segments == null) return offset;
+ int nSegments = segments.length;
+ if (nSegments <= 1) return offset;
+ int length = text.length();
+ if (length == 0) return offset;
+ if (nSegments == 2) {
+ if (segments[0] == 0 && segments[1] == length) return offset;
+ }
+ for (int i = 0; i < nSegments && offset - i >= segments[i]; i++) {
+ offset++;
+ }
+ return offset;
+}
+
+int untranslateOffset(int offset) {
+ if (segments == null) return offset;
+ int nSegments = segments.length;
+ if (nSegments <= 1) return offset;
+ int length = text.length();
+ if (length == 0) return offset;
+ if (nSegments == 2) {
+ if (segments[0] == 0 && segments[1] == length) return offset;
+ }
+ for (int i = 0; i < nSegments && offset > segments[i]; i++) {
+ offset--;
+ }
+ return offset;
+}
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java
new file mode 100644
index 0000000000..9aac18f051
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT/wpf/org/eclipse/swt/graphics/Transform.java
@@ -0,0 +1,341 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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.*;
+import org.eclipse.swt.internal.wpf.*;
+
+/**
+ * Instances of this class represent transformation matrices for
+ * points expressed as (x, y) pairs of floating point numbers.
+ * <p>
+ * Application code must explicitly invoke the <code>Transform.dispose()</code>
+ * method to release the operating system resources managed by each instance
+ * when those instances are no longer required.
+ * </p>
+ *
+ * @since 3.1
+ */
+public class Transform extends Resource {
+
+ /**
+ * the OS resource for the Transform
+ * (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;
+
+/**
+ * Constructs a new identity Transform.
+ *
+ * @param device the device on which to allocate the Transform
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Transform (Device device) {
+ this(device, 1, 0, 0, 1, 0, 0);
+}
+
+/**
+ * Constructs a new Transform given an array of elements that represent the
+ * matrix that describes the transformation.
+ *
+ * @param device the device on which to allocate the Transform
+ * @param elements an array of floats that describe the transformation matrix
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device, or the elements array is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the elements array is too small to hold the matrix values</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Transform(Device device, float[] elements) {
+ this (device, checkTransform(elements)[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
+}
+
+/**
+ * Constructs a new Transform given all of the elements that represent the
+ * matrix that describes the transformation.
+ *
+ * @param device the device on which to allocate the Transform
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
+ * </ul>
+ * @exception SWTError <ul>
+ * <li>ERROR_NO_HANDLES if a handle for the Transform could not be obtained/li>
+ * </ul>
+ *
+ * @see #dispose()
+ */
+public Transform (Device device, float m11, float m12, float m21, float m22, float dx, float dy) {
+ if (device == null) device = Device.getDevice();
+ if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ this.device = device;
+ handle = OS.gcnew_Matrix(m11, m12, m21, m22, dx, dy);
+ if (handle == 0) SWT.error(SWT.ERROR_NO_HANDLES);
+ if (device.tracking) device.new_Object(this);
+}
+
+static float[] checkTransform(float[] elements) {
+ if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ return elements;
+}
+
+/**
+ * Disposes of the operating system resources associated with
+ * the Transform. Applications must dispose of all Transforms that
+ * they allocate.
+ */
+public void dispose() {
+ if (handle == 0) return;
+ if (device.isDisposed()) return;
+ OS.GCHandle_Free(handle);
+ handle = 0;
+ if (device.tracking) device.dispose_Object(this);
+ device = null;
+}
+
+/**
+ * Fills the parameter with the values of the transformation matrix
+ * that the receiver represents, in the order {m11, m12, m21, m22, dx, dy}.
+ *
+ * @param elements array to hold the matrix values
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @exception IllegalArgumentException <ul>
+ * <li>ERROR_NULL_ARGUMENT - if the parameter is null</li>
+ * <li>ERROR_INVALID_ARGUMENT - if the parameter is too small to hold the matrix values</li>
+ * </ul>
+ */
+public void getElements(float[] elements) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (elements == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (elements.length < 6) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ elements[0] = (float)OS.Matrix_M11(handle);
+ elements[1] = (float)OS.Matrix_M12(handle);
+ elements[2] = (float)OS.Matrix_M21(handle);
+ elements[3] = (float)OS.Matrix_M22(handle);
+ elements[4] = (float)OS.Matrix_OffsetX(handle);
+ elements[5] = (float)OS.Matrix_OffsetY(handle);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * the mathematical inverse of the matrix it previously represented.
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * <li>ERROR_CANNOT_INVERT_MATRIX - if the matrix is not invertable</li>
+ * </ul>
+ */
+public void invert() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_Invert(handle);
+ //TODO handle matrix invert exception
+ //SWT.error(SWT.ERROR_CANNOT_INVERT_MATRIX);
+}
+
+/**
+ * Returns <code>true</code> if the Transform has been disposed,
+ * and <code>false</code> otherwise.
+ * <p>
+ * This method gets the dispose state for the Transform.
+ * When a Transform has been disposed, it is an error to
+ * invoke any other method using the Transform.
+ *
+ * @return <code>true</code> when the Transform is disposed, and <code>false</code> otherwise
+ */
+public boolean isDisposed() {
+ return handle == 0;
+}
+
+/**
+ * Returns <code>true</code> if the Transform represents the identity matrix
+ * and false otherwise.
+ *
+ * @return <code>true</code> if the receiver is an identity Transform, and <code>false</code> otherwise
+ */
+public boolean isIdentity() {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ return OS.Matrix_IsIdentity(handle);
+}
+
+/**
+ * Modifies the receiver such that the matrix it represents becomes the
+ * the result of multiplying the matrix it previously represented by the
+ * argument.
+ *
+ * @param matrix the matrix to multiply the receiver by
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ * @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>
+ */
+public void multiply(Transform matrix) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (matrix == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ if (matrix.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
+ int result = OS.Matrix_Multiply(handle, matrix.handle);
+ OS.Matrix_M11(handle, OS.Matrix_M11(result));
+ OS.Matrix_M12(handle, OS.Matrix_M12(result));
+ OS.Matrix_M21(handle, OS.Matrix_M21(result));
+ OS.Matrix_M22(handle, OS.Matrix_M22(result));
+ OS.Matrix_OffsetX(handle, OS.Matrix_OffsetX(result));
+ OS.Matrix_OffsetY(handle, OS.Matrix_OffsetY(result));
+ OS.GCHandle_Free(result);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation rotated by the specified angle.
+ * The angle is specified in degrees and for the identity transform 0 degrees
+ * is at the 3 o'clock position. A positive value indicates a clockwise rotation
+ * while a negative value indicates a counter-clockwise rotation.
+ *
+ * @param angle the angle to rotate the transformation by
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void rotate(float angle) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_RotatePrepend(handle, angle);
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation scaled by (scaleX, scaleY).
+ *
+ * @param scaleX the amount to scale in the X direction
+ * @param scaleY the amount to scale in the Y direction
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void scale(float scaleX, float scaleY) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_ScalePrepend(handle, scaleX, scaleY);
+}
+
+/**
+ * Modifies the receiver to represent a new transformation given all of
+ * the elements that represent the matrix that describes that transformation.
+ *
+ * @param m11 the first element of the first row of the matrix
+ * @param m12 the second element of the first row of the matrix
+ * @param m21 the first element of the second row of the matrix
+ * @param m22 the second element of the second row of the matrix
+ * @param dx the third element of the first row of the matrix
+ * @param dy the third element of the second row of the matrix
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void setElements(float m11, float m12, float m21, float m22, float dx, float dy) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_M11(handle, m11);
+ OS.Matrix_M12(handle, m12);
+ OS.Matrix_M21(handle, m21);
+ OS.Matrix_M22(handle, m22);
+ OS.Matrix_OffsetX(handle, dx);
+ OS.Matrix_OffsetY(handle, dy);
+}
+
+/**
+ * Given an array containing points described by alternating x and y values,
+ * modify that array such that each point has been replaced with the result of
+ * applying the transformation represented by the receiver to that point.
+ *
+ * @param pointArray an array of alternating x and y values to be transformed
+ *
+ * @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>
+ */
+public void transform(float[] pointArray) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
+ for (int i = 0; i < pointArray.length; i += 2) {
+ int point = OS.gcnew_Point(pointArray[i], pointArray[i + 1]);
+ int result = OS.Matrix_Transform(handle, point);
+ pointArray[i] = (float)OS.Point_X(result);
+ pointArray[i + 1] = (float)OS.Point_Y(result);
+ OS.GCHandle_Free(point);
+ OS.GCHandle_Free(result);
+ }
+}
+
+/**
+ * Modifies the receiver so that it represents a transformation that is
+ * equivalent to its previous transformation translated by (offsetX, offsetY).
+ *
+ * @param offsetX the distance to translate in the X direction
+ * @param offsetY the distance to translate in the Y direction
+ *
+ * @exception SWTException <ul>
+ * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
+ * </ul>
+ */
+public void translate(float offsetX, float offsetY) {
+ if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
+ OS.Matrix_TranslatePrepend(handle, offsetX, offsetY);
+}
+
+/**
+ * Returns a string containing a concise, human-readable
+ * description of the receiver.
+ *
+ * @return a string representation of the receiver
+ */
+public String toString() {
+ if (isDisposed()) return "Transform {*DISPOSED*}";
+ float[] elements = new float[6];
+ getElements(elements);
+ return "Transform {" + elements [0] + "," + elements [1] + "," +elements [2] + "," +elements [3] + "," +elements [4] + "," +elements [5] + "}";
+}
+
+}