/*******************************************************************************
 * 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 org.eclipse.swt.SWT;
import org.eclipse.swt.graphics2.DojoImage;
import org.eclipse.swt.graphics2.Fill;
import org.eclipse.swt.graphics2.Path;
import org.eclipse.swt.graphics2.Rect;
import org.eclipse.swt.graphics2.Shape;
import org.eclipse.swt.graphics2.Stroke;
import org.eclipse.swt.widgets.Shell;

public final class GC extends Resource {

	Drawable drawable;
	GCData data;
	
	final static int FOREGROUND = 1 << 0;
	final static int BACKGROUND = 1 << 1;
	final static int FONT = 1 << 2;
	final static int LINE_STYLE = 1 << 3;
	final static int LINE_CAP = 1 << 4;
	final static int LINE_JOIN = 1 << 5;
	final static int LINE_WIDTH = 1 << 6;
	final static int LINE_MITERLIMIT = 1 << 7;
	final static int DRAW_OFFSET = 1 << 9;
	final static int ALPHA = 1 << 10;
	final static int TRANSFORM = 1 << 11;
	final static int DRAW = TRANSFORM | ALPHA | FOREGROUND | LINE_WIDTH | LINE_STYLE  | LINE_CAP  | LINE_JOIN | LINE_MITERLIMIT | DRAW_OFFSET;
	final static int FILL = TRANSFORM | ALPHA | BACKGROUND;
	
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.gc = this;
	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);
}

void checkGC (int mask) {
	int state = data.state;
	if ((state & mask) == mask) return;
	state = (state ^ mask) & mask;	
	data.state |= mask;
	if ((state & ALPHA) != 0) {
//		callMethod("setAlpha", null, new Object[]{new Integer(data.alpha)});
	}
	if ((state & TRANSFORM) != 0) {
//		callMethod("setTransform", null, new Object[]{data.transform});
	}
	if ((state & FOREGROUND) != 0) {
//		callMethod("setForeground", null, new Object[]{new Integer(data.foreground.handle)});
	}
	if ((state & BACKGROUND) != 0) {
//		callMethod("setBackground", null, new Object[]{new Integer(data.background.handle)});
	}
	if ((state & FONT) != 0) {
//		callMethod("setFont", null, new Object[]{data.font});
	}
	if ((state & LINE_WIDTH) != 0) {
//		callMethod("setLineWidth", null, new Object[]{new Float(data.lineWidth)});
	}
	if ((state & LINE_STYLE) != 0) {}
	if ((state & LINE_MITERLIMIT) != 0) {}
	if ((state & LINE_JOIN) != 0) {}
	if ((state & LINE_CAP) != 0) {}
	if ((state & DRAW_OFFSET) != 0) {}
}

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(0, 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);
	DojoImage dImage = new DojoImage(x, y,image.width, image.height, image.imagePath);
	data.surface.createImage(dImage);
}

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 (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	//if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
	//TODO: Support transforming part of the image
	DojoImage dImage = new DojoImage(destX, destY,destWidth, destHeight, image.imagePath);
	data.surface.createImage(dImage);
}

public void drawLine (int x1, int y1, int x2, int y2) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	checkGC(DRAW);
//	callMethod("drawLine", null, new Object[]{new Integer(x1), new Integer(y1), new Integer(x2), new Integer(y2)});
}

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

public void drawPath (Path path) {
}

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

public void drawPolygon (int[] pointArray) {
}

public void drawPolyline (int[] pointArray) {
}

public void drawRectangle (int x, int y, int width, int height) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	checkGC(DRAW);
	Shape rectangle = newShape(DRAW);
	Rect rect = new Rect (rectangle, x, y, width, height, 0);
	data.surface.createRect(rect, false);
}

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);
	checkGC(DRAW);
	Shape rectangle = newShape(DRAW);
	int radius = Math.round((arcHeight/2) + ((arcWidth * arcWidth)/(8 * arcHeight)));
	Rect rect = new Rect (rectangle, x, y, width, height, radius);
	data.surface.createRect(rect, false);
}

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;
	checkGC(FONT | FOREGROUND | ((flags & SWT.DRAW_TRANSPARENT) != 0 ? 0 : BACKGROUND));
//	callMethod("drawText", null, new Object[]{string, new Integer(x), new Integer(y), new Integer(flags)});
}

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

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

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

public void fillPath (Path path) {
}

public void fillPolygon (int[] pointArray) {
}

public void fillRectangle (int x, int y, int width, int height) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	checkGC(FILL);
	Shape rectangle = newShape(FILL);
	Rect rect = new Rect (rectangle, x, y, width, height, 0);
	data.surface.createRect(rect, true);
}

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);
	checkGC(FILL);
	Shape rectangle = newShape(FILL);
	int radius = Math.round((arcHeight/2) + ((arcWidth * arcWidth)/(8 * arcHeight)));
	Rect rect = new Rect (rectangle, x, y, width, height, radius);
	data.surface.createRect(rect, true);
}

public int getAdvanceWidth (char ch) {
	return 0;
}

public boolean getAdvanced () {
	return false;
}

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

public Rectangle getClipping () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return null;
}

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 Font getFont () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return data.font;
}

public FontMetrics getFontMetrics () {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	return null;
}

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);
	if (data.transform != null) {
		float[] elements = new float[6];
		data.transform.getElements(elements);
		transform.setElements(elements[0], elements[1], elements[2], elements[3], elements[4], elements[5]);
	} 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) {
	if (data.foreground != null) data.state &= ~FOREGROUND;
	if (data.background != null)  data.state &= ~BACKGROUND;
	if (data.font != null) data.state &= ~FONT;
	data.state &= ~DRAW_OFFSET;

	Image image = data.image;
	if (image != null) image.memGC = this;
	this.drawable = drawable;
	this.data = data;
//	this.id = id;	
}

public boolean isClipped () {
	return false;
}

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

Shape newShape(int operation) {
	Shape shape = new Shape();
	Stroke stroke = shape.getStroke();
	Fill fill = shape.getFill();
	switch (operation) {
	 case FILL: 
		 configureDraw (stroke);
		 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 { 
				if (data.background != null) {
					fill.type = "color";
					fill.red = data.background.getRGB().red;
					fill.green = data.background.getRGB().green;
					fill.blue = data.background.getRGB().blue;
				} 
			 } 
		 break;
	case DRAW:
		configureDraw (stroke);
		break;
	}

	
	return shape;
}

void configureDraw(Stroke stroke) {
	switch (data.lineCap) {
		case SWT.CAP_ROUND:
			stroke.cap = "round";
		break;
		case SWT.CAP_SQUARE:
			stroke.cap="square";
		break;
		case SWT.CAP_FLAT:
		default:
			stroke.cap="butt";
		break;
	}
	
	switch (data.lineStyle) {
		case SWT.LINE_DOT:
			stroke.style="Dot";
			break;	
		case SWT.LINE_DASHDOTDOT:
			stroke.style="ShortDashDotDot";
			break;
		case SWT.LINE_DASHDOT:
			stroke.style="DashDot";
			break;
		case SWT.LINE_DASH:
			stroke.style="Dash";
			break;
		case SWT.LINE_CUSTOM:
			stroke.style="ShortDash"; 
			break;
		case SWT.LINE_SOLID:
		default:
			stroke.style="Solid";
			break;
	}
	
	switch (data.lineJoin) {
		case SWT.JOIN_BEVEL:
			stroke.join="bevel";
			break;	
		case SWT.JOIN_ROUND:
			stroke.join="round";
			break;
		case SWT.JOIN_MITER:
		default:
			stroke.join="miter";
			stroke.miter=Math.round(data.lineMiterLimit);
			break;
	}
	
	if (data.foreground != null) {
		stroke.red = data.foreground.getRGB().red;
		stroke.green = data.foreground.getRGB().green;
		stroke.blue = data.foreground.getRGB().blue;
	} 
	
	stroke.width = Math.max(1, Math.round(data.lineWidth));
}

public void setAdvanced (boolean advanced) {
}

public void setAntialias (int antialias) {
}

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

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;
	data.state &= ~BACKGROUND;
}

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;
	data.state &= ~BACKGROUND;
}

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

public void setClipping (Path path) {
}

public void setClipping (Rectangle rect) {
}

public void setClipping (Region region) {
}

public void setFillRule (int rule) {
}

public void setFont (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;
	data.state &= ~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;
	data.state &= ~FOREGROUND;
}

public void setForegroundPattern (Pattern pattern) {
}

public void setInterpolation (int interpolation) {
}

public void setLineAttributes (LineAttributes attributes) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (attributes == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
	int mask = 0;
	float lineWidth = attributes.width;
	if (lineWidth != data.lineWidth) {
		mask |= LINE_WIDTH | DRAW_OFFSET;
	}
	int lineStyle = attributes.style;
	if (lineStyle != data.lineStyle) {
		mask |= LINE_STYLE;
		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) {
		mask |= LINE_JOIN;
		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) {
		mask |= LINE_CAP;
		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;
			mask |= LINE_STYLE;
		} else {
			dashes = lineDashes;
		}
	} else {
		if (lineDashes != null && lineDashes.length > 0) {
			mask |= LINE_STYLE;
		} else {
			dashes = lineDashes;
		}
	}
	float dashOffset = attributes.dashOffset;
	if (dashOffset != data.lineDashesOffset) {
		mask |= LINE_STYLE;		
	}
	float miterLimit = attributes.miterLimit;
	if (miterLimit != data.lineMiterLimit) {
		mask |= LINE_MITERLIMIT;		
	}
	if (mask == 0) return;
	data.lineWidth = lineWidth;
	data.lineStyle = lineStyle;
	data.lineCap = cap;
	data.lineJoin = join;
	data.lineDashes = dashes;
	data.lineDashesOffset = dashOffset;
	data.lineMiterLimit = miterLimit;
	data.state &= ~mask;
}

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;
	data.state &= ~LINE_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;
	}
	data.state &= ~LINE_STYLE;
}

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;
	data.state &= ~LINE_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;
	data.state &= ~LINE_STYLE;
}

public void setLineWidth (int lineWidth) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	if (data.lineWidth == lineWidth) return;
	data.lineWidth = lineWidth;
	data.state &= ~(LINE_WIDTH | DRAW_OFFSET);	
}

public void setTextAntialias (int antialias) {
}

public void setTransform (Transform transform) {
	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	data.transform = transform;
	data.state &= ~TRANSFORM;
}

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);
	checkGC(FONT);
//	return (Point)callMethod("textExtent", "org.eclipse.swt.graphics.Point", new Object[]{string, new Integer(flags)});
	return new Point(0, 0);
}

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

}
