/*******************************************************************************
 * Copyright (c) 2000, 2008 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 intrinsic.Array;
import intrinsic.flash.display.*;
import intrinsic.flash.geom.Matrix;
import intrinsic.flash.text.TextField;
import intrinsic.flash.text.TextFormat;
import intrinsic.flash.text.TextFieldAutoSize;
import intrinsic.flash.text.TextLineMetrics;

import org.eclipse.swt.*;

public final class GC extends Resource {

	Drawable drawable;
	GCData data;
	
	final static int DRAW = 1;
	final static int FILL = 2;

GC() {
}

public GC (Drawable drawable) {
	this(drawable, 0);
}

public GC (Drawable drawable, int style) {
	if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	GCData data = new GCData();
	data.style = checkStyle(style);
	int id = 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, id);
}

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);
}

TextField newTextField(int operation, String string, int flags) {
	TextField text = new TextField();
	text.text = string;
	text.autoSize = TextFieldAutoSize.LEFT;
	text.selectable = false;
	text.mouseEnabled = false;
	TextFormat format = new TextFormat();
	switch (operation) {
		case DRAW:
			if (data.matrix != null) text.transform.matrix = data.matrix;
			if (data.clip != null) text.mask = data.clip;
			if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
				text.background = true;
				//TODO pattern
				text.backgroundColor = data.background.handle;
			}
			text.textColor = data.foreground.handle;
			format.color = new intrinsic.Number(data.foreground.handle);
			break;
	}
	org.eclipse.swt.graphics.Font font = data.font;
	format.font = font.fontFamily;
	format.size = new intrinsic.Number(font.fontSize);
	if (font.fontStyle.equals("italic")) format.italic = font.fontStyle;
	if (font.fontWeight.equals("bold")) format.bold = font.fontWeight;
	text.defaultTextFormat = format;
	if (string.length() > 0) {
		text.setTextFormat(format, 0, string.length());
	}
	return text;
}

Shape newShape (int operation) {
	Shape shape = new Shape();
	Graphics graphics = shape.graphics;
	if (data.matrix != null) shape.transform.matrix = data.matrix;
	if (data.clip != null) shape.mask = data.clip;
	switch(operation) {
		case FILL:
			Pattern pattern = data.backgroundPattern;
			if (pattern != null) {
				Image image = pattern.image;
				if (image != null) {
					graphics.beginBitmapFill(image.object, null, true, false);
				} else {
					Array colors = new Array();
					colors.push(pattern.color1.handle);
					colors.push(pattern.color2.handle);
					Array alphas = new Array();
					alphas.push(pattern.alpha1 / 255f);
					alphas.push(pattern.alpha2 / 255f);
					Array ratios = new Array();
					ratios.push(0);
					ratios.push(255);
					Matrix matrix = new Matrix(1, 0, 0, 1, 0, 0);
					float width = pattern.x2 - pattern.x1;
					float height = pattern.y2 - pattern.y1;
					float rotation = height == 0 ? 0 : width / height;
					matrix.createGradientBox(width, height, rotation, pattern.x1, pattern.y1);
					graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
				}
			} else {
				graphics.beginFill(data.background.handle, data.alpha / 255f);
			}
			break;
		case DRAW:
			String caps = CapsStyle.NONE;
			switch (data.lineCap) {
				case SWT.CAP_ROUND: caps = CapsStyle.ROUND; break;
				case SWT.CAP_SQUARE: caps = CapsStyle.SQUARE; break;
			}
			String joints = JointStyle.MITER;
			switch (data.lineJoin) {
				case SWT.JOIN_ROUND: joints = JointStyle.ROUND; break;
				case SWT.JOIN_BEVEL: joints = JointStyle.BEVEL; break;
			}
			graphics.lineStyle(data.lineWidth, data.foreground.handle, data.alpha / 255f, false, "normal", caps, joints, data.lineMiterLimit);
			break;
	}
	data.sprite.addChild(shape);
	return shape;
}

public void copyArea (Image image, int x, int y) {
}

public void copyArea (int srcX, int srcY, int width, int height, int destX, int destY) {
}

public void copyArea (int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) {
}

void destroy () {
	/* Free resources */
	Image image = data.image;
	if (image != null) {
		image.memGC = null;
	}

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

	drawable = null;
	data.image = null;
	data.device = null;
	data.foreground = null;
	data.foregroundPattern = null;
	data.background = null;
	data.backgroundPattern = null;
	data.font = null;
	data.lineDashes = null;
	data = null;
}

public void drawArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
}

public void drawFocus (int x, int y, int width, int height) {
}

public void drawImage (Image image, int x, int y) {
	if (isDisposed()) 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);
}

public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
	if (isDisposed()) 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 imgWidth = image.object.width;
 	int imgHeight = image.object.height;
 	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);
		}
 	}
	Bitmap bitmap = new Bitmap(image.object);
	if (data.matrix != null) {
		bitmap.transform.matrix = (Matrix)data.matrix.clone();
		intrinsic.flash.geom.Point point = new intrinsic.flash.geom.Point(destX, destY);
		point = data.matrix.transformPoint(point);
		bitmap.x = point.x;
		bitmap.y = point.y;
	} else {
		bitmap.x = destX;
		bitmap.y = destY;
	}
	if (data.clip != null) bitmap.mask = data.clip;
	bitmap.scrollRect = new intrinsic.flash.geom.Rectangle(srcX, srcY, srcWidth, srcHeight);
	if (srcWidth != destWidth) bitmap.scaleX *= destWidth / (float)srcWidth;
	if (srcHeight != destHeight) bitmap.scaleY *= destHeight / (float)srcHeight;
	//TODO interpolation
	data.sprite.addChild(bitmap);
}

public void drawLine (int x1, int y1, int x2, int y2) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(DRAW);
	Graphics graphics = shape.graphics;
	graphics.moveTo(x1, y1);
	graphics.lineTo(x2, y2);
}

public void drawOval (int x, int y, int width, int height) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(DRAW);
	Graphics graphics = shape.graphics;
	graphics.drawEllipse(x, y, width, height);
}

public void drawPath (Path path) {
}

public void drawPoint (int x, int y) {
}

public void drawPolygon (int[] pointArray) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (pointArray == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(DRAW);
	Graphics graphics = shape.graphics;
	graphics.moveTo(pointArray[0], pointArray[1]);
	for (int i = 2; i < pointArray.length; i += 2) {
		graphics.lineTo(pointArray[i], pointArray[i+1]);
	}
	graphics.lineTo(pointArray[0], pointArray[1]);
}

public void drawPolyline (int[] pointArray) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (pointArray == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(DRAW);
	Graphics graphics = shape.graphics;
	graphics.moveTo(pointArray[0], pointArray[1]);
	for (int i = 2; i < pointArray.length; i+= 2) {
		graphics.lineTo(pointArray[i], pointArray[i+1]);
	}
}

public void drawRectangle (int x, int y, int width, int height) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(DRAW);
	Graphics graphics = shape.graphics;
	graphics.drawRect(x, y, width, height);
}

public void drawRectangle (Rectangle rect) {
	if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	drawRectangle (rect.x, rect.y, rect.width, rect.height);
}

public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(DRAW);
	Graphics graphics = shape.graphics;
	graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
}

public void drawString (String string, int x, int y) {
	drawString(string, x, y, false);
}

public void drawString (String string, int x, int y, boolean isTransparent) {
	drawText(string, x, y, isTransparent ? SWT.DRAW_TRANSPARENT : 0);
}

public void drawText (String string, int x, int y) {
	drawText(string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
}

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);
}

public void drawText (String string, int x, int y, int flags) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (string.length() == 0) return;
	TextField text = newTextField(DRAW, string, flags);
	if (data.matrix != null) {
		intrinsic.flash.geom.Point point = new intrinsic.flash.geom.Point(x, y);
		point = data.matrix.transformPoint(point);
		text.x = point.x;
		text.y = point.y;		
	} else {
		text.x = x;
		text.y = y;
	}
	data.sprite.addChild(text);
}

public boolean equals (Object object) {
	if (object == this) return true;
	if (!(object instanceof GC)) return false;
	GC gc = (GC) object;
	return device == gc.device && drawable == gc.drawable;
}

public void fillArc (int x, int y, int width, int height, int startAngle, int arcAngle) {
}

public void fillGradientRectangle (int x, int y, int width, int height, boolean vertical) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(0);
	Graphics graphics = shape.graphics;
	Array colors = new Array();
	colors.push(data.foreground.handle);
	colors.push(data.background.handle);
	Array alphas = new Array();
	alphas.push(data.alpha / 255f);
	alphas.push(data.alpha / 255f);
	Array ratios = new Array();
	ratios.push(0);
	ratios.push(255);
	Matrix matrix = new Matrix(1, 0, 0, 1, 0, 0);
	matrix.createGradientBox(width, height, vertical ? Math.PI / 2f : 0, x, y);
	graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix, SpreadMethod.PAD, InterpolationMethod.RGB, 0);
	graphics.drawRect(x, y, width, height);
	graphics.endFill();
}

public void fillOval (int x, int y, int width, int height) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(FILL);
	Graphics graphics = shape.graphics;
	graphics.drawEllipse(x, y, width, height);
	graphics.endFill();
}

public void fillPath (Path path) {
}

public void fillPolygon (int[] pointArray) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (pointArray == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(FILL);
	Graphics graphics = shape.graphics;
	graphics.moveTo(pointArray[0], pointArray[1]);
	for (int i = 2; i < pointArray.length; i += 2) {
		graphics.lineTo(pointArray[i], pointArray[i+1]);
	}
	graphics.lineTo(pointArray[0], pointArray[1]);
	graphics.endFill();
}

public void fillRectangle (int x, int y, int width, int height) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(FILL);
	Graphics graphics = shape.graphics;
	graphics.drawRect(x, y, width, height);
	graphics.endFill();
}

public void fillRectangle (Rectangle rect) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	fillRectangle(rect.x, rect.y, rect.width, rect.height);
}

public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = newShape(FILL);
	Graphics graphics = shape.graphics;
	graphics.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
	graphics.endFill();
}

public static GC flex_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;
}

public int getAdvanceWidth (char ch) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return stringExtent(String.valueOf(ch)).x;
}

public boolean getAdvanced () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return true;
}

public int getAlpha () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.alpha;
}

public int getAntialias () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.antialias;
}

public Color getBackground () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.background;
}

public Pattern getBackgroundPattern () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.backgroundPattern;	
}

public int getCharWidth (char ch) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return stringExtent(String.valueOf(ch)).x;
}

public Rectangle getClipping () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	//TODO include clipping
	Rectangle rect = new Rectangle(0, 0, 0, 0);
	Image image = data.image;
	if (image != null) {
		rect.width = image.object.width;
		rect.height = image.object.height;
	} else {
		rect.width = (int)data.sprite.parent.width;
		rect.height = (int)data.sprite.parent.height;
		intrinsic.flash.geom.Rectangle paint = data.paintRect;
		if (paint != null) {
			rect.intersect(new Rectangle((int)paint.x, (int)paint.y, (int)paint.width, (int)paint.height));
		}
	}
	return rect;
}

public void getClipping (Region region) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
}

public int getFillRule () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.fillRule;
}

public org.eclipse.swt.graphics.Font getFont () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.font;
}

public FontMetrics getFontMetrics () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	String str = "0123456789abcdefghijklmnopqrstuvxwz";
	TextField text = newTextField(0, str, 0);
	TextLineMetrics mt = text.getLineMetrics(0);
	return FontMetrics.internal_new((int)mt.ascent, (int)mt.descent, (int)mt.height, (int)mt.width / str.length());
}

public Color getForeground () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.foreground;
}

public Pattern getForegroundPattern () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.foregroundPattern;
}

public GCData getGCData () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data;
}

public int getInterpolation () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return 0;
}

public LineAttributes getLineAttributes () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	float[] dashes = null;
	if (data.lineDashes != null) {
		dashes = new float[data.lineDashes.length];
		System.arraycopy(data.lineDashes, 0, dashes, 0, dashes.length);
	}
	return new LineAttributes(data.lineWidth, data.lineCap, data.lineJoin, data.lineStyle, dashes, data.lineDashesOffset, data.lineMiterLimit);
}

public int getLineCap () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.lineCap;
}

public int[] getLineDash () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (data.lineDashes == null) return null;
	int[] lineDashes = new int[data.lineDashes.length];
	for (int i = 0; i < lineDashes.length; i++) {
		lineDashes[i] = (int)data.lineDashes[i];
	}
	return lineDashes;
}

public int getLineJoin () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.lineJoin;
}

public int getLineStyle () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.lineStyle;
}

public int getLineWidth () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return (int)data.lineWidth;
}

public int getStyle () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.style;
}

public int getTextAntialias () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.textAntialias;
}

public void getTransform (Transform transform) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (transform == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	if (transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	Matrix matrix = data.matrix;
	if (matrix != null) {
		transform.setElements((float)matrix.a, (float)matrix.b, (float)matrix.c, (float)matrix.d, (float)matrix.tx, (float)matrix.ty);
	} else {
		transform.setElements(1, 0, 0, 1, 0, 0);
	}
}

public boolean getXORMode () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.xorMode;
}

public int hashCode () {
	return super.hashCode();
}

void init(Drawable drawable, GCData data, int id) {
	Image image = data.image;
	if (image != null) image.memGC = this;
	this.drawable = drawable;
	this.data = data;
}

public boolean isClipped () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.clip != null;
}

public boolean isDisposed () {
	return device == null;
}

public void setAdvanced (boolean advanced) {
}

public void setAntialias (int antialias) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
}

public void setAlpha (int alpha) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	data.alpha = alpha & 0xFF;
}

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);
	data.background = color;
	data.backgroundPattern = null;
}

public void setBackgroundPattern (Pattern pattern) {
	if (isDisposed()) 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;
}

public void setClipping (int x, int y, int width, int height) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	Shape shape = new Shape();
	if (data.matrix != null) {
		shape.transform.matrix = (Matrix)data.matrix.clone();
	}
	Graphics graphics = shape.graphics;
	graphics.beginFill(0xFFFFFF, 1);
	graphics.drawRect(x, y, width, height);
	data.sprite.addChild(shape);
	data.clip = shape;
}

public void setClipping (Path path) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
}

public void setClipping (Rectangle rect) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (rect == null) {
		data.clip = null;
	} else {
		setClipping(rect.x, rect.y, rect.width, rect.height);
	}
}

public void setClipping (Region region) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (region == null) {
		data.clip = null;
	} else {
		//TODO - clone
//		if (data.matrix != null) {
//			shape.transform.matrix = (Matrix)data.matrix.clone();
//		}
		data.clip = region.object;
//		data.sprite.addChild(region.object);
	}
}

public void setFillRule (int rule) {
}

public void setFont (org.eclipse.swt.graphics.Font font) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (font == null) font = data.device.systemFont;
	if (font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	data.font = font;
}

public void setForeground (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);
	data.foreground = color;
	data.foregroundPattern = null;
}

public void setForegroundPattern (Pattern pattern) {
	if (isDisposed()) 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;
}

public void setInterpolation (int interpolation) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
}

public void setLineAttributes (LineAttributes attributes) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (attributes == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	float lineWidth = attributes.width;
	int lineStyle = attributes.style;
	if (lineStyle != data.lineStyle) {
		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 (attributes.dash == null) lineStyle = SWT.LINE_SOLID;
				break;
			default:
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
	}
	int join = attributes.join;
	if (join != data.lineJoin) {
		switch (join) {
			case SWT.CAP_ROUND:
			case SWT.CAP_FLAT:
			case SWT.CAP_SQUARE:
				break;
			default:
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
	}
	int cap = attributes.join;
	if (cap != data.lineCap) {
		switch (cap) {
			case SWT.JOIN_MITER:
			case SWT.JOIN_ROUND:
			case SWT.JOIN_BEVEL:
				break;
			default:
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
	}
	float[] dashes = attributes.dash;
	float[] lineDashes = data.lineDashes;
	if (dashes != null && dashes.length > 0) {
		boolean changed = lineDashes == null || lineDashes.length != dashes.length;
		for (int i = 0; i < dashes.length; i++) {
			float dash = dashes[i];
			if (dash <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
			if (!changed && lineDashes[i] != dash) changed = true;
		}
		if (changed) {
			float[] newDashes = new float[dashes.length];
			System.arraycopy(dashes, 0, newDashes, 0, dashes.length);
			dashes = newDashes;
		} else {
			dashes = lineDashes;
		}
	} else {
		if (!(lineDashes != null && lineDashes.length > 0)) {
			dashes = lineDashes;
		}
	}
	float dashOffset = attributes.dashOffset;
	float miterLimit = attributes.miterLimit;
	data.lineWidth = lineWidth;
	data.lineStyle = lineStyle;
	data.lineCap = cap;
	data.lineJoin = join;
	data.lineDashes = dashes;
	data.lineDashesOffset = dashOffset;
	data.lineMiterLimit = miterLimit;
}

public void setLineCap (int cap) {
	if (isDisposed()) 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;
}

public void setLineDash (int[] dashes) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	float[] 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 float[dashes.length];
		for (int i = 0; i < dashes.length; i++) {
			data.lineDashes[i] = dashes[i];
		}
		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;
	}
}

public void setLineJoin (int join) {
	if (isDisposed()) 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;
}

public void setLineStyle (int lineStyle) {
	if (isDisposed()) 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;
}

public void setLineWidth (int lineWidth) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (data.lineWidth == lineWidth) return;
	data.lineWidth = lineWidth;	
}

public void setTextAntialias (int antialias) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	data.textAntialias = antialias;
}

public void setTransform (Transform transform) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (transform != null && transform.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	if (transform == null) {
		data.matrix = null;
	} else {
		data.matrix = (Matrix)transform.object.clone();
	}
}

public void setXORMode (boolean xor) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	data.xorMode = xor;
}

public Point stringExtent (String string) {
	return textExtent(string, 0);
}

public Point textExtent (String string) {
	return textExtent(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
}

public Point textExtent (String string, int flags) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (string == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	TextField text = newTextField(0, string, flags);
	return new Point((int)text.width, (int)text.height);
}

public String toString () {
	if (isDisposed()) return "GC {*DISPOSED*}";
	return "GC {" + data.sprite + "}";
}

}
