Java tutorial
/******************************************************************************* * Copyright (c) 2013 EclipseSource 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: * EclipseSource - initial API and implementation ******************************************************************************/ package org.eclipse.swt.graphics; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTError; import org.eclipse.swt.SWTException; /** * 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 2.1 */ public class Path extends Resource { private PointF currentPoint; private PointF startPoint; private byte[] types; private float[] points; /** * 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> * * @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); currentPoint = new PointF(); startPoint = new PointF(); types = new byte[0]; points = new float[0]; moveTo(0, 0); } /** * 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> * * @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() */ public Path(Device device, PathData data) { this(device); if (data == null) { SWT.error(SWT.ERROR_NULL_ARGUMENT); } appendData(data); } /** * 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); } appendData(path.getPathData()); if (currentPoint.x != path.currentPoint.x || currentPoint.y != path.currentPoint.y) { moveTo(path.currentPoint.x, path.currentPoint.y); } } /** * 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); } moveTo(x, y); lineTo(x + width, y); lineTo(x + width, y + height); lineTo(x, y + height); close(); currentPoint.x = x; currentPoint.y = y; } /** * 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); } addPoint(SWT.PATH_MOVE_TO, x, y); currentPoint.x = x; currentPoint.y = y; startPoint.x = x; startPoint.y = y; } /** * 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); } addPoint(SWT.PATH_LINE_TO, x, y); currentPoint.x = x; currentPoint.y = y; } /** * 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); } addPoint(SWT.PATH_QUAD_TO, cx, cy, x, y); currentPoint.x = x; currentPoint.y = y; } /** * 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); } addPoint(SWT.PATH_CUBIC_TO, cx1, cy1, cx2, cy2, x, y); currentPoint.x = x; currentPoint.y = y; } /** * 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); } addPoint(SWT.PATH_CLOSE); currentPoint.x = startPoint.x; currentPoint.y = startPoint.y; } /** * 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); } int typesLength = types.length; int pointsLength = points.length; if (getLastPointType() == SWT.PATH_MOVE_TO) { typesLength--; pointsLength -= 2; } PathData result = new PathData(); result.types = new byte[typesLength]; result.points = new float[pointsLength]; System.arraycopy(types, 0, result.types, 0, typesLength); System.arraycopy(points, 0, result.points, 0, pointsLength); return result; } /** * 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); } point[0] = currentPoint.x; point[1] = currentPoint.y; } @Override void destroy() { types = null; points = null; } private void appendData(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); } } } private void addPoint(int type, float... coords) { if (type != SWT.PATH_MOVE_TO || getLastPointType() != SWT.PATH_MOVE_TO) { enlargeArrays(1, coords.length); } types[types.length - 1] = (byte) type; for (int i = coords.length; i > 0; i--) { points[points.length - i] = coords[coords.length - i]; } } private int getLastPointType() { return types.length > 0 ? types[types.length - 1] : SWT.NONE; } private void enlargeArrays(int typesAmount, int pointsAmount) { if (typesAmount > 0) { byte[] newTypes = new byte[types.length + typesAmount]; System.arraycopy(types, 0, newTypes, 0, types.length); types = newTypes; } if (pointsAmount > 0) { float[] newPoints = new float[points.length + pointsAmount]; System.arraycopy(points, 0, newPoints, 0, points.length); points = newPoints; } } private final class PointF { public float x; public float y; } }