home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 11.5 KB | 437 lines |
- /*
- * @(#)BasicStroke.java 1.18 98/03/18
- *
- * Copyright 1997, 1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- package java.awt;
-
- import java.awt.geom.GeneralPath;
- import java.awt.geom.PathIterator;
- import sun.dc.path.FastPathProducer;
- import sun.dc.path.PathConsumer;
- import sun.dc.path.PathException;
- import sun.dc.pr.PathStroker;
- import sun.dc.pr.PathDasher;
- import sun.dc.pr.Rasterizer;
-
- /**
- * Defines a basic set of rendering attributes for stroked graphics
- * primitives.
- * These attributes describe the shape of a pen drawn along the
- * trajectory of the path and the decorations applied where path
- * segments are joined and where they begin and end.
- * These attributes include:
- * <dl compact>
- * <dt><i>width</i>
- * <dd>The width of the pen measured perpendicular to its trajectory.
- * <dt><i>end caps</i>
- * <dd>The decoration of the path where line segments begin and end.
- * <dt><i>line joins</i>
- * <dd>The decoration of the path between connected line segments.
- * <dt><i>dash attributes</i>
- * <dd>The definition of how to make a dash pattern along the
- * trajectory of the path by creating new segments which alternate
- * between opaque and transparent sections.
- * </dl>
- *
- * @version 10 Feb 1997
- * @author Jim Graham
- */
- public class BasicStroke implements Stroke {
-
- /**
- * Join line segments by extending their outside edges until
- * they meet.
- */
- public final static int JOIN_MITER = 0;
-
- /**
- * Join line segments by rounding off the corner at a radius
- * of half the line width.
- */
- public final static int JOIN_ROUND = 1;
-
- /**
- * Join line segments by connecting the outer corners of their
- * wide outlines with a straight segment.
- */
- public final static int JOIN_BEVEL = 2;
-
- /**
- * End unclosed subpaths and dash segments with no added
- * decoration.
- */
- public final static int CAP_BUTT = 0;
-
- /**
- * End unclosed subpaths and dash segments with a round
- * decoration with radius equal to half of the line width.
- */
- public final static int CAP_ROUND = 1;
-
- /**
- * End unclosed subpaths and dash segments with a square
- * projection that extends beyond the end of the segment
- * to a distance equal to half of the line width.
- */
- public final static int CAP_SQUARE = 2;
-
- float width;
-
- int join;
- int cap;
- float miterlimit;
-
- float dash[];
- float dash_phase;
-
- /**
- * Construct a new stroke with the specified attributes.
- * @param width The width of the stroke.
- * @param cap The style of the ends of a stroke.
- * @param join The style to join strokes together.
- * @param miterlimit The limit to trim the miter join.
- * @param dash The array representing the dashing pattern.
- * @param dash_phase The offset to start the dashing pattern.
- */
- public BasicStroke(float width, int cap, int join, float miterlimit,
- float dash[], float dash_phase) {
- if (width < 0.0f) {
- throw new IllegalArgumentException("negative width");
- }
- if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) {
- throw new IllegalArgumentException("illegal end cap value");
- }
- if (join == JOIN_MITER) {
- if (miterlimit < 0.0f) {
- throw new IllegalArgumentException("negative miter limit");
- }
- } else if (join != JOIN_ROUND && join != JOIN_BEVEL) {
- throw new IllegalArgumentException("illegal line join value");
- }
- if (dash != null) {
- if (dash_phase < 0.0f) {
- throw new IllegalArgumentException("negative dash phase");
- }
- boolean allzero = true;
- for (int i = 0; i < dash.length; i++) {
- float d = dash[i];
- if (d > 0.0) {
- allzero = false;
- } else if (d < 0.0) {
- throw new IllegalArgumentException("negative dash length");
- }
- }
- if (allzero) {
- throw new IllegalArgumentException("dash lengths all zero");
- }
- }
- this.width = width;
- this.cap = cap;
- this.join = join;
- this.miterlimit = miterlimit;
- this.dash = dash;
- this.dash_phase = dash_phase;
- }
-
- /**
- * Construct a new stroke with the specified attributes, but
- * no dashing.
- * @param width The width of the stroke.
- * @param cap The style of the ends of a stroke.
- * @param join The style to join strokes together.
- * @param miterlimit The limit to trim the miter join.
- */
- public BasicStroke(float width, int cap, int join, float miterlimit) {
- this(width, cap, join, miterlimit, null, 0.0f);
- }
-
- /**
- * Construct a new stroke with the specified attributes, but
- * no dashing. The miter limit parameter is unnecessary in
- * cases where the default is allowable or the line joins
- * are not specified as JOIN_MITER.
- * @param width The width of the stroke.
- * @param cap The style of the ends of a stroke.
- * @param join The style to join strokes together.
- */
- public BasicStroke(float width, int cap, int join) {
- this(width, cap, join, 10.0f, null, 0.0f);
- }
-
- /**
- * Construct a new stroke with the specified line width, and
- * with default values for the cap and join styles and no dashing.
- * @param width The width of the stroke.
- */
- public BasicStroke(float width) {
- this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
- }
-
- /**
- * Construct a new stroke with defaults for all attributes.
- * The default attributes are a line width of 1.0, CAP_SQUARE,
- * JOIN_MITER, a miter limit of 10.0, and no dashing.
- */
- public BasicStroke() {
- this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);
- }
-
-
- /**
- * Returns a shape whose interior defines the stroked outline of
- * a given shape.
- * @param s The shape whose boundary should be stroked.
- * @return The shape of the stroked outline.
- * @see Stroke#createStrokedShape
- */
- public Shape createStrokedShape(Shape s) {
- FillAdapter filler = new FillAdapter();
- PathStroker stroker = new PathStroker(filler);
- PathConsumer consumer;
-
- stroker.setPenDiameter(width);
- stroker.setPenT4(null);
- stroker.setCaps(RasterizerCaps[cap]);
- stroker.setCorners(RasterizerCorners[join], miterlimit);
- if (dash != null) {
- PathDasher dasher = new PathDasher(stroker);
- dasher.setDash(dash, dash_phase);
- dasher.setDashT4(null);
- consumer = dasher;
- } else {
- consumer = stroker;
- }
-
- PathIterator pi = s.getPathIterator(null);
-
- try {
- consumer.beginPath();
- boolean pathClosed = false;
- float mx = 0.0f;
- float my = 0.0f;
- float point[] = new float[6];
-
- while (!pi.isDone()) {
- int type = pi.currentSegment(point);
- if (pathClosed == true) {
- pathClosed = false;
- if (type != PathIterator.SEG_MOVETO) {
- // Force current point back to last moveto point
- consumer.beginSubpath(mx, my);
- }
- }
- switch (type) {
- case PathIterator.SEG_MOVETO:
- mx = point[0];
- my = point[1];
- consumer.beginSubpath(point[0], point[1]);
- break;
- case PathIterator.SEG_LINETO:
- consumer.appendLine(point[0], point[1]);
- break;
- case PathIterator.SEG_QUADTO:
- // Quadratic curves take two points
- consumer.appendQuadratic(point[0], point[1],
- point[2], point[3]);
- break;
- case PathIterator.SEG_CUBICTO:
- // Cubic curves take three points
- consumer.appendCubic(point[0], point[1],
- point[2], point[3],
- point[4], point[5]);
- break;
- case PathIterator.SEG_CLOSE:
- consumer.closedSubpath();
- pathClosed = true;
- break;
- }
- pi.next();
- }
-
- consumer.endPath();
- } catch (PathException e) {
- throw new InternalError("Unable to Stroke shape ("+
- e.getMessage()+")");
- }
-
- return filler.getShape();
- }
-
- /**
- * Returns the line width. Line width is represented in user space.
- * @return The line width of the stroke.
- */
- public float getLineWidth() {
- return width;
- }
-
- /**
- * Returns the end cap style.
- * @return The end cap style of the stroke.
- */
- public int getEndCap() {
- return cap;
- }
-
- /**
- * Returns the line join style.
- * @return The line join style of the stroke.
- */
- public int getLineJoin() {
- return join;
- }
-
- /**
- * Returns the limit of miter joins.
- * @return The limit of miter joins.
- */
- public float getMiterLimit() {
- return miterlimit;
- }
-
- /**
- * Return the array representing the lengths of the dash segments.
- * Alternate entries in the array represent the user space lengths
- * of the opaque and transparent segments of the dashes.
- * As the pen moves along the path to be stroked, the user space
- * distance that the pen travels will be accumulated to index
- * into the dash array.
- * The pen will be opaque when its current cumulative distance maps
- * to an odd element of the dash array and transparent otherwise.
- * @return The dash array.
- */
- public float[] getDashArray() {
- if (dash == null) {
- return null;
- }
- float ret[] = new float[dash.length];
- System.arraycopy(dash, 0, ret, 0, dash.length);
- return ret;
- }
-
- /**
- * Returns the dash phase.
- * The dash phase is a user space distance that is used to initialize
- * the path distance accumulation variable before the first segment
- * of the first subpath is stroked.
- * @return the dash phase.
- */
- public float getDashPhase() {
- return dash_phase;
- }
-
- public boolean equals(Object obj) {
- if (!(obj instanceof BasicStroke)) {
- return false;
- }
-
- BasicStroke bs = (BasicStroke) obj;
- if (width != bs.width) {
- return false;
- }
-
- if (join != bs.join) {
- return false;
- }
-
- if (cap != bs.cap) {
- return false;
- }
-
- if (miterlimit != bs.miterlimit) {
- return false;
- }
-
- if (dash != null) {
- if (!dash.equals(bs.dash)) {
- return false;
- }
- }
- else if (bs.dash != null) {
- return false;
- }
-
- if (dash_phase != bs.dash_phase) {
- return false;
- }
-
- return true;
- }
-
- private static final int RasterizerCaps[] = {
- Rasterizer.BUTT, Rasterizer.ROUND, Rasterizer.SQUARE
- };
-
- private static final int RasterizerCorners[] = {
- Rasterizer.MITER, Rasterizer.ROUND, Rasterizer.BEVEL
- };
-
- private class FillAdapter implements PathConsumer {
- boolean closed;
- GeneralPath path;
-
- public FillAdapter() {
- path = new GeneralPath(GeneralPath.NON_ZERO);
- }
-
- public Shape getShape() {
- return path;
- }
-
- public void beginPath() {}
-
- public void beginSubpath(float x0, float y0) {
- if (closed) {
- path.closePath();
- closed = false;
- }
- path.moveTo(x0, y0);
- }
-
- public void appendLine(float x1, float y1) {
- path.lineTo(x1, y1);
- }
-
- public void appendQuadratic(float xm, float ym, float x1, float y1) {
- path.quadTo(xm, ym, x1, y1);
- }
-
- public void appendCubic(float xm, float ym,
- float xn, float yn,
- float x1, float y1) {
- path.curveTo(xm, ym, xn, yn, x1, y1);
- }
-
- public void closedSubpath() {
- closed = true;
- }
-
- public void endPath() {
- if (closed) {
- path.closePath();
- closed = false;
- }
- }
-
- public void useProxy(FastPathProducer proxy)
- throws PathException
- {
- proxy.sendTo(this);
- }
-
- public long getCPathConsumer() {
- return 0;
- }
- }
- }
-