/* | 
|
 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. | 
|
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 
|
 * | 
|
 * This code is free software; you can redistribute it and/or modify it | 
|
 * under the terms of the GNU General Public License version 2 only, as | 
|
 * published by the Free Software Foundation.  Oracle designates this | 
|
 * particular file as subject to the "Classpath" exception as provided | 
|
 * by Oracle in the LICENSE file that accompanied this code. | 
|
 * | 
|
 * This code is distributed in the hope that it will be useful, but WITHOUT | 
|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 
|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License | 
|
 * version 2 for more details (a copy is included in the LICENSE file that | 
|
 * accompanied this code). | 
|
 * | 
|
 * You should have received a copy of the GNU General Public License version | 
|
 * 2 along with this work; if not, write to the Free Software Foundation, | 
|
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | 
|
 * | 
|
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | 
|
 * or visit www.oracle.com if you need additional information or have any | 
|
 * questions. | 
|
*/  | 
|
package java.awt;  | 
|
import java.beans.ConstructorProperties;  | 
|
import java.lang.annotation.Native;  | 
|
/** | 
|
 * The <code>BasicStroke</code> class defines a basic set of rendering | 
|
 * attributes for the outlines of graphics primitives, which are rendered | 
|
 * with a {@link Graphics2D} object that has its Stroke attribute set to | 
|
 * this <code>BasicStroke</code>. | 
|
 * The rendering attributes defined by <code>BasicStroke</code> describe | 
|
 * the shape of the mark made by a pen drawn along the outline of a | 
|
 * {@link Shape} and the decorations applied at the ends and joins of | 
|
 * path segments of the <code>Shape</code>. | 
|
 * These rendering attributes include: | 
|
 * <dl> | 
|
 * <dt><i>width</i> | 
|
 * <dd>The pen width, measured perpendicularly to the pen trajectory. | 
|
 * <dt><i>end caps</i> | 
|
 * <dd>The decoration applied to the ends of unclosed subpaths and | 
|
 * dash segments.  Subpaths that start and end on the same point are | 
|
 * still considered unclosed if they do not have a CLOSE segment. | 
|
 * See {@link java.awt.geom.PathIterator#SEG_CLOSE SEG_CLOSE} | 
|
 * for more information on the CLOSE segment. | 
|
 * The three different decorations are: {@link #CAP_BUTT}, | 
|
 * {@link #CAP_ROUND}, and {@link #CAP_SQUARE}. | 
|
 * <dt><i>line joins</i> | 
|
 * <dd>The decoration applied at the intersection of two path segments | 
|
 * and at the intersection of the endpoints of a subpath that is closed | 
|
 * using {@link java.awt.geom.PathIterator#SEG_CLOSE SEG_CLOSE}. | 
|
 * The three different decorations are: {@link #JOIN_BEVEL}, | 
|
 * {@link #JOIN_MITER}, and {@link #JOIN_ROUND}. | 
|
 * <dt><i>miter limit</i> | 
|
 * <dd>The limit to trim a line join that has a JOIN_MITER decoration. | 
|
 * A line join is trimmed when the ratio of miter length to stroke | 
|
 * width is greater than the miterlimit value.  The miter length is | 
|
 * the diagonal length of the miter, which is the distance between | 
|
 * the inside corner and the outside corner of the intersection. | 
|
 * The smaller the angle formed by two line segments, the longer | 
|
 * the miter length and the sharper the angle of intersection.  The | 
|
 * default miterlimit value of 10.0f causes all angles less than | 
|
 * 11 degrees to be trimmed.  Trimming miters converts | 
|
 * the decoration of the line join to bevel. | 
|
 * <dt><i>dash attributes</i> | 
|
 * <dd>The definition of how to make a dash pattern by alternating | 
|
 * between opaque and transparent sections. | 
|
 * </dl> | 
|
 * All attributes that specify measurements and distances controlling | 
|
 * the shape of the returned outline are measured in the same | 
|
 * coordinate system as the original unstroked <code>Shape</code> | 
|
 * argument.  When a <code>Graphics2D</code> object uses a | 
|
 * <code>Stroke</code> object to redefine a path during the execution | 
|
 * of one of its <code>draw</code> methods, the geometry is supplied | 
|
 * in its original form before the <code>Graphics2D</code> transform | 
|
 * attribute is applied.  Therefore, attributes such as the pen width | 
|
 * are interpreted in the user space coordinate system of the | 
|
 * <code>Graphics2D</code> object and are subject to the scaling and | 
|
 * shearing effects of the user-space-to-device-space transform in that | 
|
 * particular <code>Graphics2D</code>. | 
|
 * For example, the width of a rendered shape's outline is determined | 
|
 * not only by the width attribute of this <code>BasicStroke</code>, | 
|
 * but also by the transform attribute of the | 
|
 * <code>Graphics2D</code> object.  Consider this code: | 
|
 * <blockquote><tt> | 
|
 *      // sets the Graphics2D object's Transform attribute | 
|
 *      g2d.scale(10, 10); | 
|
 *      // sets the Graphics2D object's Stroke attribute | 
|
 *      g2d.setStroke(new BasicStroke(1.5f)); | 
|
 * </tt></blockquote> | 
|
 * Assuming there are no other scaling transforms added to the | 
|
 * <code>Graphics2D</code> object, the resulting line | 
|
 * will be approximately 15 pixels wide. | 
|
 * As the example code demonstrates, a floating-point line | 
|
 * offers better precision, especially when large transforms are | 
|
 * used with a <code>Graphics2D</code> object. | 
|
 * When a line is diagonal, the exact width depends on how the | 
|
 * rendering pipeline chooses which pixels to fill as it traces the | 
|
 * theoretical widened outline.  The choice of which pixels to turn | 
|
 * on is affected by the antialiasing attribute because the | 
|
 * antialiasing rendering pipeline can choose to color | 
|
 * partially-covered pixels. | 
|
 * <p> | 
|
 * For more information on the user space coordinate system and the | 
|
 * rendering process, see the <code>Graphics2D</code> class comments. | 
|
 * @see Graphics2D | 
|
 * @author Jim Graham | 
|
*/  | 
|
public class BasicStroke implements Stroke {  | 
|
    /** | 
|
     * Joins path segments by extending their outside edges until | 
|
     * they meet. | 
|
*/  | 
|
@Native public final static int JOIN_MITER = 0;  | 
|
    /** | 
|
     * Joins path segments by rounding off the corner at a radius | 
|
     * of half the line width. | 
|
*/  | 
|
@Native public final static int JOIN_ROUND = 1;  | 
|
    /** | 
|
     * Joins path segments by connecting the outer corners of their | 
|
     * wide outlines with a straight segment. | 
|
*/  | 
|
@Native public final static int JOIN_BEVEL = 2;  | 
|
    /** | 
|
     * Ends unclosed subpaths and dash segments with no added | 
|
     * decoration. | 
|
*/  | 
|
@Native public final static int CAP_BUTT = 0;  | 
|
    /** | 
|
     * Ends unclosed subpaths and dash segments with a round | 
|
     * decoration that has a radius equal to half of the width | 
|
     * of the pen. | 
|
*/  | 
|
@Native public final static int CAP_ROUND = 1;  | 
|
    /** | 
|
     * Ends 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. | 
|
*/  | 
|
@Native public final static int CAP_SQUARE = 2;  | 
|
float width;  | 
|
int join;  | 
|
int cap;  | 
|
float miterlimit;  | 
|
float dash[];  | 
|
float dash_phase;  | 
|
    /** | 
|
     * Constructs a new <code>BasicStroke</code> with the specified | 
|
     * attributes. | 
|
     * @param width the width of this <code>BasicStroke</code>.  The | 
|
     *         width must be greater than or equal to 0.0f.  If width is | 
|
     *         set to 0.0f, the stroke is rendered as the thinnest | 
|
     *         possible line for the target device and the antialias | 
|
     *         hint setting. | 
|
     * @param cap the decoration of the ends of a <code>BasicStroke</code> | 
|
     * @param join the decoration applied where path segments meet | 
|
     * @param miterlimit the limit to trim the miter join.  The miterlimit | 
|
     *        must be greater than or equal to 1.0f. | 
|
     * @param dash the array representing the dashing pattern | 
|
     * @param dash_phase the offset to start the dashing pattern | 
|
     * @throws IllegalArgumentException if <code>width</code> is negative | 
|
     * @throws IllegalArgumentException if <code>cap</code> is not either | 
|
     *         CAP_BUTT, CAP_ROUND or CAP_SQUARE | 
|
     * @throws IllegalArgumentException if <code>miterlimit</code> is less | 
|
     *         than 1 and <code>join</code> is JOIN_MITER | 
|
     * @throws IllegalArgumentException if <code>join</code> is not | 
|
     *         either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER | 
|
     * @throws IllegalArgumentException if <code>dash_phase</code> | 
|
     *         is negative and <code>dash</code> is not <code>null</code> | 
|
     * @throws IllegalArgumentException if the length of | 
|
     *         <code>dash</code> is zero | 
|
     * @throws IllegalArgumentException if dash lengths are all zero. | 
|
*/  | 
|
    @ConstructorProperties({ "lineWidth", "endCap", "lineJoin", "miterLimit", "dashArray", "dashPhase" }) | 
|
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 < 1.0f) {  | 
|
throw new IllegalArgumentException("miter limit < 1");  | 
|
}  | 
|
} 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;  | 
|
if (dash != null) {  | 
|
this.dash = (float []) dash.clone();  | 
|
}  | 
|
this.dash_phase = dash_phase;  | 
|
}  | 
|
    /** | 
|
     * Constructs a solid <code>BasicStroke</code> with the specified | 
|
     * attributes. | 
|
     * @param width the width of the <code>BasicStroke</code> | 
|
     * @param cap the decoration of the ends of a <code>BasicStroke</code> | 
|
     * @param join the decoration applied where path segments meet | 
|
     * @param miterlimit the limit to trim the miter join | 
|
     * @throws IllegalArgumentException if <code>width</code> is negative | 
|
     * @throws IllegalArgumentException if <code>cap</code> is not either | 
|
     *         CAP_BUTT, CAP_ROUND or CAP_SQUARE | 
|
     * @throws IllegalArgumentException if <code>miterlimit</code> is less | 
|
     *         than 1 and <code>join</code> is JOIN_MITER | 
|
     * @throws IllegalArgumentException if <code>join</code> is not | 
|
     *         either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER | 
|
*/  | 
|
    public BasicStroke(float width, int cap, int join, float miterlimit) { | 
|
this(width, cap, join, miterlimit, null, 0.0f);  | 
|
}  | 
|
    /** | 
|
     * Constructs a solid <code>BasicStroke</code> with the specified | 
|
     * attributes.  The <code>miterlimit</code> 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 <code>BasicStroke</code> | 
|
     * @param cap the decoration of the ends of a <code>BasicStroke</code> | 
|
     * @param join the decoration applied where path segments meet | 
|
     * @throws IllegalArgumentException if <code>width</code> is negative | 
|
     * @throws IllegalArgumentException if <code>cap</code> is not either | 
|
     *         CAP_BUTT, CAP_ROUND or CAP_SQUARE | 
|
     * @throws IllegalArgumentException if <code>join</code> is not | 
|
     *         either JOIN_ROUND, JOIN_BEVEL, or JOIN_MITER | 
|
*/  | 
|
    public BasicStroke(float width, int cap, int join) { | 
|
this(width, cap, join, 10.0f, null, 0.0f);  | 
|
}  | 
|
    /** | 
|
     * Constructs a solid <code>BasicStroke</code> with the specified | 
|
     * line width and with default values for the cap and join | 
|
     * styles. | 
|
     * @param width the width of the <code>BasicStroke</code> | 
|
     * @throws IllegalArgumentException if <code>width</code> is negative | 
|
*/  | 
|
    public BasicStroke(float width) { | 
|
this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);  | 
|
}  | 
|
    /** | 
|
     * Constructs a new <code>BasicStroke</code> with defaults for all | 
|
     * attributes. | 
|
     * The default attributes are a solid line of width 1.0, CAP_SQUARE, | 
|
     * JOIN_MITER, a miter limit of 10.0. | 
|
*/  | 
|
    public BasicStroke() { | 
|
this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f);  | 
|
}  | 
|
    /** | 
|
     * Returns a <code>Shape</code> whose interior defines the | 
|
     * stroked outline of a specified <code>Shape</code>. | 
|
     * @param s the <code>Shape</code> boundary be stroked | 
|
     * @return the <code>Shape</code> of the stroked outline. | 
|
*/  | 
|
public Shape createStrokedShape(Shape s) {  | 
|
sun.java2d.pipe.RenderingEngine re =  | 
|
sun.java2d.pipe.RenderingEngine.getInstance();  | 
|
return re.createStrokedShape(s, width, cap, join, miterlimit,  | 
|
dash, dash_phase);  | 
|
}  | 
|
    /** | 
|
     * Returns the line width.  Line width is represented in user space, | 
|
     * which is the default-coordinate space used by Java 2D.  See the | 
|
     * <code>Graphics2D</code> class comments for more information on | 
|
     * the user space coordinate system. | 
|
     * @return the line width of this <code>BasicStroke</code>. | 
|
     * @see Graphics2D | 
|
*/  | 
|
    public float getLineWidth() { | 
|
return width;  | 
|
}  | 
|
    /** | 
|
     * Returns the end cap style. | 
|
     * @return the end cap style of this <code>BasicStroke</code> as one | 
|
     * of the static <code>int</code> values that define possible end cap | 
|
     * styles. | 
|
*/  | 
|
    public int getEndCap() { | 
|
return cap;  | 
|
}  | 
|
    /** | 
|
     * Returns the line join style. | 
|
     * @return the line join style of the <code>BasicStroke</code> as one | 
|
     * of the static <code>int</code> values that define possible line | 
|
     * join styles. | 
|
*/  | 
|
    public int getLineJoin() { | 
|
return join;  | 
|
}  | 
|
    /** | 
|
     * Returns the limit of miter joins. | 
|
     * @return the limit of miter joins of the <code>BasicStroke</code>. | 
|
*/  | 
|
    public float getMiterLimit() { | 
|
return miterlimit;  | 
|
}  | 
|
    /** | 
|
     * Returns 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 outline of the <code>Shape</code> | 
|
     * to be stroked, the user space | 
|
     * distance that the pen travels is accumulated.  The distance | 
|
     * value is used to index into the dash array. | 
|
     * The pen is opaque when its current cumulative distance maps | 
|
     * to an even element of the dash array and transparent otherwise. | 
|
     * @return the dash array. | 
|
*/  | 
|
    public float[] getDashArray() { | 
|
if (dash == null) {  | 
|
return null;  | 
|
}  | 
|
return (float[]) dash.clone();  | 
|
}  | 
|
    /** | 
|
     * Returns the current dash phase. | 
|
     * The dash phase is a distance specified in user coordinates that | 
|
     * represents an offset into the dashing pattern. In other words, the dash | 
|
     * phase defines the point in the dashing pattern that will correspond to | 
|
     * the beginning of the stroke. | 
|
     * @return the dash phase as a <code>float</code> value. | 
|
*/  | 
|
    public float getDashPhase() { | 
|
return dash_phase;  | 
|
}  | 
|
    /** | 
|
     * Returns the hashcode for this stroke. | 
|
     * @return      a hash code for this stroke. | 
|
*/  | 
|
    public int hashCode() { | 
|
int hash = Float.floatToIntBits(width);  | 
|
hash = hash * 31 + join;  | 
|
hash = hash * 31 + cap;  | 
|
hash = hash * 31 + Float.floatToIntBits(miterlimit);  | 
|
if (dash != null) {  | 
|
hash = hash * 31 + Float.floatToIntBits(dash_phase);  | 
|
for (int i = 0; i < dash.length; i++) {  | 
|
hash = hash * 31 + Float.floatToIntBits(dash[i]);  | 
|
}  | 
|
}  | 
|
return hash;  | 
|
}  | 
|
/**  | 
|
* Returns true if this BasicStroke represents the same  | 
|
* stroking operation as the given argument.  | 
|
*/  | 
|
   /** | 
|
    * Tests if a specified object is equal to this <code>BasicStroke</code> | 
|
    * by first testing if it is a <code>BasicStroke</code> and then comparing | 
|
    * its width, join, cap, miter limit, dash, and dash phase attributes with | 
|
    * those of this <code>BasicStroke</code>. | 
|
    * @param  obj the specified object to compare to this | 
|
    *              <code>BasicStroke</code> | 
|
    * @return <code>true</code> if the width, join, cap, miter limit, dash, and | 
|
    *            dash phase are the same for both objects; | 
|
    *            <code>false</code> otherwise. | 
|
*/  | 
|
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_phase != bs.dash_phase) {  | 
|
return false;  | 
|
}  | 
|
if (!java.util.Arrays.equals(dash, bs.dash)) {  | 
|
return false;  | 
|
}  | 
|
}  | 
|
else if (bs.dash != null) {  | 
|
return false;  | 
|
}  | 
|
return true;  | 
|
}  | 
|
}  |