/*******************************************************************************
 * Copyright (c) 2000, 2012 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.cocoa.*;

/**
 * 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>
 * <p>
 * This class requires the operating system's advanced graphics subsystem
 * which may not be available on some platforms.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#path">Path, Pattern snippets</a>
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: GraphicsExample</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 *
 * @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>
	 *
	 * @noreference This field is not intended to be referenced by clients.
	 */
	public NSBezierPath handle;

	boolean closed = true;

/**
 * Constructs a new empty Path.
 * <p>
 * This operation requires the operating system's advanced
 * graphics subsystem which may not be available on some
 * platforms.
 * </p>
 * <p>
 * You must dispose the path when it is no longer required.
 * </p>
 *
 * @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 SWTException <ul>
 *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</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) {
	super(device);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		handle = NSBezierPath.bezierPath();
		if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES);
		handle.retain();
		handle.moveToPoint(new NSPoint());
		init();
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * Constructs a new Path that is a copy of <code>path</code>. If
 * <code>flatness</code> is less than or equal to zero, an unflatten
 * copy of the path is created. Otherwise, it specifies the maximum
 * error between the path and its flatten copy. Smaller numbers give
 * better approximation.
 * <p>
 * This operation requires the operating system's advanced
 * graphics subsystem which may not be available on some
 * platforms.
 * </p>
 * <p>
 * You must dispose the path when it is no longer required.
 * </p>
 *
 * @param device the device on which to allocate the path
 * @param path the path to make a copy
 * @param flatness the flatness value
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
 *    <li>ERROR_NULL_ARGUMENT - if the path is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the path has been disposed</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
 * </ul>
 *
 * @see #dispose()
 * @since 3.4
 */
public Path (Device device, Path path, float flatness) {
	super(device);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		if (path == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		if (path.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		flatness = Math.max(0, flatness);
		if (flatness == 0) {
			handle = new NSBezierPath(path.handle.copy().id);
		} else {
			double /*float*/ defaultFlatness = NSBezierPath.defaultFlatness();
			NSBezierPath.setDefaultFlatness(flatness);
			handle = path.handle.bezierPathByFlatteningPath();
			handle.retain();
			NSBezierPath.setDefaultFlatness(defaultFlatness);
		}
		if (handle == null) SWT.error(SWT.ERROR_NO_HANDLES);
		init();
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * Constructs a new Path with the specified PathData.
 * <p>
 * This operation requires the operating system's advanced
 * graphics subsystem which may not be available on some
 * platforms.
 * </p>
 * <p>
 * You must dispose the path when it is no longer required.
 * </p>
 *
 * @param device the device on which to allocate the path
 * @param data the data for the path
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the device is null and there is no current device</li>
 *    <li>ERROR_NULL_ARGUMENT - if the data is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_NO_GRAPHICS_LIBRARY - if advanced graphics are not available</li>
 * </ul>
 * @exception SWTError <ul>
 *    <li>ERROR_NO_HANDLES if a handle for the path could not be obtained</li>
 * </ul>
 *
 * @see #dispose()
 * @since 3.4
 */
public Path (Device device, PathData data) {
	this(device);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		if (data == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
		init(data);
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		NSAffineTransform transform = NSAffineTransform.transform();
		transform.translateXBy(x + width / 2f, y + height / 2f);
		transform.scaleXBy(width / 2f, height / 2f);
		NSBezierPath path = NSBezierPath.bezierPath();
		NSPoint center = new NSPoint();
		float sAngle = -startAngle;
		float eAngle = -(startAngle + arcAngle);
		path.appendBezierPathWithArcWithCenter(center, 1, sAngle,  eAngle, arcAngle>0);
		path.transformUsingAffineTransform(transform);
//		handle.appendBezierPath(path);
		appendBezierPath(path);
		if (closed = (Math.abs(arcAngle) >= 360)) {
			handle.closePath();
		}
	} finally {
		if (pool != null) pool.release();
	}
}

void appendBezierPath (NSBezierPath path) {
	int count = (int)/*64*/path.elementCount();
	long /*int*/ points = OS.malloc(3 * NSPoint.sizeof);
	if (points == 0) SWT.error(SWT.ERROR_NO_HANDLES);
	NSPoint pt1 = new NSPoint();
	NSPoint pt2 = new NSPoint();
	NSPoint pt3 = new NSPoint();
	for (int i = 0; i < count; i++) {
		int element = (int)/*64*/path.elementAtIndex(i, points);
		switch (element) {
			case OS.NSMoveToBezierPathElement:
				OS.memmove(pt1, points, NSPoint.sizeof);
				if (closed) {
					handle.moveToPoint(pt1);
				} else {
					handle.lineToPoint(pt1);
				}
				break;
			case OS.NSLineToBezierPathElement:
				OS.memmove(pt1, points, NSPoint.sizeof);
				handle.lineToPoint(pt1);
				closed = false;
				break;
			case OS.NSCurveToBezierPathElement:
				OS.memmove(pt1, points, NSPoint.sizeof);
				OS.memmove(pt2, points + NSPoint.sizeof, NSPoint.sizeof);
				OS.memmove(pt3, points + NSPoint.sizeof + NSPoint.sizeof, NSPoint.sizeof);
				handle.curveToPoint(pt3, pt1, pt2);
				closed = false;
				break;
			case OS.NSClosePathBezierPathElement:
				handle.closePath();
				closed = true;
				break;
		}
	}
	OS.free(points);
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		handle.appendBezierPath(path.handle);
		closed = path.closed;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSRect rect = new NSRect();
	rect.x = x;
	rect.y = y;
	rect.width = width;
	rect.height = height;
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		handle.appendBezierPathWithRect(rect);
		closed = true;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		closed = true;
		NSString str = NSString.stringWith(string);
		NSTextStorage textStorage = (NSTextStorage)new NSTextStorage().alloc().init();
		NSLayoutManager layoutManager = (NSLayoutManager)new NSLayoutManager().alloc().init();
		NSTextContainer textContainer = (NSTextContainer)new NSTextContainer().alloc();
		NSSize size = new NSSize();
		size.width = OS.MAX_TEXT_CONTAINER_SIZE;
		size.height = OS.MAX_TEXT_CONTAINER_SIZE;
		textContainer.initWithContainerSize(size);
		textContainer.setLineFragmentPadding(0);
		textStorage.addLayoutManager(layoutManager);
		layoutManager.addTextContainer(textContainer);
		NSRange range = new NSRange();
		range.length = str.length();
		/*
		* Feature in Cocoa. Adding attributes directly to a NSTextStorage causes
		* output to the console and eventually a segmentation fault when printing
		* on a thread other than the main thread. The fix is to add attributes to
		* a separate NSMutableAttributedString and add it to text storage when done.
		*/
		NSMutableAttributedString attrStr = (NSMutableAttributedString)new NSMutableAttributedString().alloc();
		attrStr.id = attrStr.initWithString(str).id;
		attrStr.beginEditing();
		attrStr.addAttribute(OS.NSFontAttributeName, font.handle, range);
		font.addTraits(attrStr, range);
		attrStr.endEditing();
		textStorage.setAttributedString(attrStr);
		attrStr.release();
		range = layoutManager.glyphRangeForTextContainer(textContainer);
		if (range.length != 0) {
			long /*int*/ glyphs = OS.malloc((range.length + 1) * 4);
			long /*int*/ count = layoutManager.getGlyphs(glyphs, range);
			NSBezierPath path = NSBezierPath.bezierPath();
			for (int i = 0; i < count; i++) {
				NSPoint pt = layoutManager.locationForGlyphAtIndex(i);
				NSRect lineFragmentRect = layoutManager.lineFragmentUsedRectForGlyphAtIndex(i, 0);
				NSFont actualFont = new NSFont(textStorage.attribute(OS.NSFontAttributeName, layoutManager.characterIndexForGlyphAtIndex(i), 0));
				pt.x = pt.x + x + lineFragmentRect.x;
				pt.y =  - pt.y - y - lineFragmentRect.y;
				path.moveToPoint(pt);
				path.appendBezierPathWithGlyphs(glyphs + (i * 4), 1, actualFont);
			}
			OS.free(glyphs);
			NSAffineTransform transform = NSAffineTransform.transform();
			transform.scaleXBy(1, -1);
			path.transformUsingAffineTransform(transform);
			handle.appendBezierPath(path);
		}
		textContainer.release();
		layoutManager.release();
		textStorage.release();
	} finally  {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		handle.closePath();
		closed = true;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		//TODO - see windows
		if (outline) {
			long /*int*/ pixel = OS.malloc(4);
			if (pixel == 0) SWT.error(SWT.ERROR_NO_HANDLES);
			int[] buffer = new int[]{0xFFFFFFFF};
			OS.memmove(pixel, buffer, 4);
			long /*int*/ colorspace = OS.CGColorSpaceCreateDeviceRGB();
			long /*int*/ context = OS.CGBitmapContextCreate(pixel, 1, 1, 8, 4, colorspace, OS.kCGImageAlphaNoneSkipFirst);
			OS.CGColorSpaceRelease(colorspace);
			if (context == 0) {
				OS.free(pixel);
				SWT.error(SWT.ERROR_NO_HANDLES);
			}
			GCData data = gc.data;
			int capStyle = 0;
			switch (data.lineCap) {
				case SWT.CAP_ROUND: capStyle = OS.kCGLineCapRound; break;
				case SWT.CAP_FLAT: capStyle = OS.kCGLineCapButt; break;
				case SWT.CAP_SQUARE: capStyle = OS.kCGLineCapSquare; break;
			}
			OS.CGContextSetLineCap(context, capStyle);
			int joinStyle = 0;
			switch (data.lineJoin) {
				case SWT.JOIN_MITER: joinStyle = OS.kCGLineJoinMiter; break;
				case SWT.JOIN_ROUND: joinStyle = OS.kCGLineJoinRound; break;
				case SWT.JOIN_BEVEL: joinStyle = OS.kCGLineJoinBevel; break;
			}
			OS.CGContextSetLineJoin(context, joinStyle);
			OS.CGContextSetLineWidth(context, data.lineWidth);
			OS.CGContextTranslateCTM(context, -x + 0.5f, -y + 0.5f);
			long /*int*/ path = GC.createCGPathRef(handle);
			OS.CGContextAddPath(context, path);
			OS.CGPathRelease(path);
			OS.CGContextStrokePath(context);
			OS.CGContextRelease(context);
			OS.memmove(buffer, pixel, 4);
			OS.free(pixel);
			return buffer[0] != 0xFFFFFFFF;
		} else {
			NSPoint point = new NSPoint();
			point.x = x;
			point.y = y;
			return handle.containsPoint(point);
		}
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		NSPoint pt = new NSPoint();
		pt.x = x;
		pt.y = y;
		NSPoint ct1 = new NSPoint();
		ct1.x = cx1;
		ct1.y = cy1;
		NSPoint ct2 = new NSPoint();
		ct2.x = cx2;
		ct2.y = cy2;
		handle.curveToPoint(pt, ct1, ct2);
		closed = false;
	} finally {
		if (pool != null) pool.release();
	}
}

@Override
void destroy() {
	handle.release();
	handle = 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		NSRect rect = handle.controlPointBounds();
		bounds[0] = (float)/*64*/rect.x;
		bounds[1] = (float)/*64*/rect.y;
		bounds[2] = (float)/*64*/rect.width;
		bounds[3] = (float)/*64*/rect.height;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		NSPoint pt = handle.currentPoint();
		point[0] = (float)/*64*/pt.x;
		point[1] = (float)/*64*/pt.y;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		int count = (int)/*64*/handle.elementCount();
		int pointCount = 0, typeCount = 0;
		byte[] types = new byte[count];
		float[] pointArray = new float[count * 6];
		long /*int*/ points = OS.malloc(3 * NSPoint.sizeof);
		if (points == 0) SWT.error(SWT.ERROR_NO_HANDLES);
		NSPoint pt = new NSPoint();
		for (int i = 0; i < count; i++) {
			int element = (int)/*64*/handle.elementAtIndex(i, points);
			switch (element) {
				case OS.NSMoveToBezierPathElement:
					types[typeCount++] = SWT.PATH_MOVE_TO;
					OS.memmove(pt, points, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					break;
				case OS.NSLineToBezierPathElement:
					types[typeCount++] = SWT.PATH_LINE_TO;
					OS.memmove(pt, points, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					break;
				case OS.NSCurveToBezierPathElement:
					types[typeCount++] = SWT.PATH_CUBIC_TO;
					OS.memmove(pt, points, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					OS.memmove(pt, points + NSPoint.sizeof, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					OS.memmove(pt, points + NSPoint.sizeof + NSPoint.sizeof, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					break;
				case OS.NSClosePathBezierPathElement:
					types[typeCount++] = SWT.PATH_CLOSE;
					break;
			}
		}
		OS.free(points);
		if (pointCount != pointArray.length) {
			float[] temp = new float[pointCount];
			System.arraycopy(pointArray, 0, temp, 0, pointCount);
			pointArray = temp;
		}
		PathData data = new PathData();
		data.types = types;
		data.points = pointArray;
		return data;
	} finally {
		if (pool != null)  pool.release();
	}
}

void init(PathData data) {
	byte[] types = data.types;
	float[] points = data.points;
	for (int i = 0, j = 0; i < types.length; i++) {
		switch (types[i]) {
			case SWT.PATH_MOVE_TO:
				moveTo(points[j++], points[j++]);
				break;
			case SWT.PATH_LINE_TO:
				lineTo(points[j++], points[j++]);
				break;
			case SWT.PATH_CUBIC_TO:
				cubicTo(points[j++], points[j++], points[j++], points[j++], points[j++], points[j++]);
				break;
			case SWT.PATH_QUAD_TO:
				quadTo(points[j++], points[j++], points[j++], points[j++]);
				break;
			case SWT.PATH_CLOSE:
				close();
				break;
			default:
				dispose();
				SWT.error(SWT.ERROR_INVALID_ARGUMENT);
		}
	}
}

/**
 * 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 (except {@link #dispose()}) using the Path.
 *
 * @return <code>true</code> when the Path is disposed, and <code>false</code> otherwise
 */
@Override
public boolean isDisposed() {
	return handle == null;
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		NSPoint pt = new NSPoint();
		pt.x = x;
		pt.y = y;
		handle.lineToPoint(pt);
		closed = false;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		NSPoint pt = new NSPoint();
		pt.x = x;
		pt.y = y;
		handle.moveToPoint(pt);
		closed = true;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * 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);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		NSPoint current = handle.isEmpty() ? new NSPoint() : handle.currentPoint();
		NSPoint ct1 = new NSPoint();
		ct1.x = current.x + 2 * (cx - current.x) / 3;
		ct1.y = current.y + 2 * (cy - current.y) / 3;
		NSPoint ct2 = new NSPoint();
		ct2.x = ct1.x + (x - current.x) / 3;
		ct2.y = ct1.y + (y - current.y) / 3;
		NSPoint pt = new NSPoint();
		pt.x = x;
		pt.y = y;
		handle.curveToPoint(pt, ct1, ct2);
		closed = false;
	} finally {
		if (pool != null) pool.release();
	}
}

/**
 * Returns a string containing a concise, human-readable
 * description of the receiver.
 *
 * @return a string representation of the receiver
 */
@Override
public String toString () {
	if (isDisposed()) return "Path {*DISPOSED*}";
	return "Path {" + handle + "}";
}

}
