Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.layout; 027 028import java.util.ArrayList; 029import java.util.Collections; 030import java.util.List; 031import javafx.scene.shape.StrokeLineCap; 032import javafx.scene.shape.StrokeLineJoin; 033import javafx.scene.shape.StrokeType; 034 035/** 036 * Defines the style of the stroke to use on one side of a BorderStroke. There are 037 * several predefined styles, although the properties of these predefined styles may 038 * not match the settings used to ultimately draw them. Or you may create a new 039 * BorderStrokeStyle and define each of the stroke settings manually, similar 040 * to any {@link javafx.scene.shape.Shape}. 041 */ 042public final class BorderStrokeStyle { 043 private static final List<Double> DOTTED_LIST = Collections.unmodifiableList(asList(0, 2)); 044 private static final List<Double> DASHED_LIST = Collections.unmodifiableList(asList(2, 1.4)); 045 046 /** 047 * Indicates that no stroke should be drawn. 048 */ 049 public static final BorderStrokeStyle NONE = new BorderStrokeStyle( 050 StrokeType.INSIDE, StrokeLineJoin.MITER, StrokeLineCap.BUTT, 0, 0, null); 051 052 /** 053 * A predefined dotted pattern to be used for stroking 054 */ 055 public static final BorderStrokeStyle DOTTED = new BorderStrokeStyle( 056 StrokeType.INSIDE, StrokeLineJoin.MITER, StrokeLineCap.ROUND, 10, 0, DOTTED_LIST); 057 058 /** 059 * A predefined dashed pattern to be used for stroking 060 */ 061 public static final BorderStrokeStyle DASHED = new BorderStrokeStyle( 062 StrokeType.INSIDE, StrokeLineJoin.MITER, StrokeLineCap.BUTT, 10, 0, DASHED_LIST); 063 064 /** 065 * A predefined solid line to be used for stroking 066 */ 067 public static final BorderStrokeStyle SOLID = new BorderStrokeStyle( 068 StrokeType.INSIDE, StrokeLineJoin.MITER, StrokeLineCap.BUTT, 10, 0, null); 069 070 /** 071 * Defines the direction (inside, outside, or both) that the strokeWidth 072 * is applied to the boundary of the shape. 073 * 074 * @defaultValue CENTERED 075 */ 076 private final StrokeType type; 077 public final StrokeType getType() { return type; } 078 079 /** 080 * Defines the decoration applied where path segments meet. 081 * The value must have one of the following values: 082 * {@code StrokeLineJoin.BEVEL}, {@code StrokeLineJoin.MITER}, 083 * and {@code StrokeLineJoin.ROUND}. 084 * 085 * @defaultValue MITER 086 */ 087 private final StrokeLineJoin lineJoin; 088 public final StrokeLineJoin getLineJoin() { return lineJoin; } 089 090 /** 091 * The end cap style of this {@code Shape} as one of the following 092 * values that define possible end cap styles: 093 * {@code StrokeLineCap.BUTT}, {@code StrokeLineCap.ROUND}, 094 * and {@code StrokeLineCap.SQUARE}. 095 * 096 * @defaultValue SQUARE 097 */ 098 private final StrokeLineCap lineCap; 099 public final StrokeLineCap getLineCap() { return lineCap; } 100 101 /** 102 * Defines the limit for the {@code StrokeLineJoin.MITER} line join style. 103 * 104 * @defaultValue 10 105 */ 106 private final double miterLimit; 107 public final double getMiterLimit() { return miterLimit; } 108 109 /** 110 * Defines a distance specified in user coordinates that represents 111 * an offset into the dashing pattern. In other words, the dash phase 112 * defines the point in the dashing pattern that will correspond 113 * to the beginning of the stroke. 114 * 115 * @defaultValue 0 116 */ 117 private final double dashOffset; 118 public final double getDashOffset() { return dashOffset; } 119 120 /** 121 * Defines the array representing the lengths of the dash segments. 122 * Alternate entries in the array represent the user space lengths 123 * of the opaque and transparent segments of the dashes. 124 * As the pen moves along the outline of the {@code Shape} to be stroked, 125 * the user space distance that the pen travels is accumulated. 126 * The distance value is used to index into the dash array. 127 * The pen is opaque when its current cumulative distance maps 128 * to an even element of the dash array and transparent otherwise. 129 * An empty dashArray indicates a solid line with no spaces. 130 * @defaultValue empty 131 */ 132 private final List<Double> dashArray; 133 public final List<Double> getDashArray() { return dashArray; } 134 135 /** 136 * A cached hash code 137 */ 138 private final int hash; 139 140 /** 141 * Creates a new BorderStrokeStyle. 142 * 143 * @param type The type of stroke, whether rendered OUTSIDE, INSIDE, or CENTERED on the 144 * border line. If null, defaults to CENTERED. 145 * @param lineJoin The line join. If null, defaults to MITER 146 * @param lineCap The line cap. If null, defaults to BUTT. 147 * @param miterLimit The miter limit. 10 is a good default value. 148 * @param dashOffset The dashOffset. 0 is a good default value. 149 * @param dashArray The dash array. If null, defaults to an empty list. 150 */ 151 public BorderStrokeStyle(StrokeType type, StrokeLineJoin lineJoin, 152 StrokeLineCap lineCap, double miterLimit, 153 double dashOffset, List<Double> dashArray) { 154 this.type = (type != null) ? 155 type : StrokeType.CENTERED; 156 this.lineJoin = (lineJoin != null) ? 157 lineJoin : StrokeLineJoin.MITER; 158 this.lineCap = (lineCap != null) ? 159 lineCap : StrokeLineCap.BUTT; 160 this.miterLimit = miterLimit; 161 this.dashOffset = dashOffset; 162 163 if (dashArray == null) { 164 this.dashArray = Collections.emptyList(); 165 } else { 166 if (dashArray == DASHED_LIST || dashArray == DOTTED_LIST) { 167 // We want to use the SAME EXACT LIST in the case of DASHED_LIST or DOTTED_LIST 168 // so that code in NGRegion can execute specialized code paths for such cases. 169 this.dashArray = dashArray; 170 } else { 171 // Must not allow the passed in array to inadvertently mutate the 172 // state of this BorderStrokeStyle! 173 List<Double> list = new ArrayList<Double>(dashArray); 174 this.dashArray = Collections.unmodifiableList(list); 175 } 176 } 177 178 // Pre-compute the hash code. NOTE: all variables are prefixed with "this" so that we 179 // do not accidentally compute the hash based on the constructor arguments rather than 180 // based on the fields themselves! 181 int result; 182 long temp; 183 result = this.type.hashCode(); 184// result = 31 * result + (this == NONE ? 0 : 1); // TODO OH NO. NONE hasn't been assigned yet. 185 result = 31 * result + this.lineJoin.hashCode(); 186 result = 31 * result + this.lineCap.hashCode(); 187 temp = this.miterLimit != +0.0d ? Double.doubleToLongBits(this.miterLimit) : 0L; 188 result = 31 * result + (int) (temp ^ (temp >>> 32)); 189 temp = this.dashOffset != +0.0d ? Double.doubleToLongBits(this.dashOffset) : 0L; 190 result = 31 * result + (int) (temp ^ (temp >>> 32)); 191 result = 31 * result + this.dashArray.hashCode(); 192 hash = result; 193 } 194 195 /** 196 * @inheritDoc 197 */ 198 @Override public String toString() { 199 if (this == NONE) { 200 return "BorderStyle.NONE"; 201 } else if (this == DASHED) { 202 return "BorderStyle.DASHED"; 203 } else if (this == DOTTED) { 204 return "BorderStyle.DOTTED"; 205 } else if (this == SOLID) { 206 return "BorderStyle.SOLID"; 207 } else { 208 StringBuilder buffer = new StringBuilder(); 209 buffer.append("BorderStyle: "); 210 buffer.append(type); 211 buffer.append(", "); 212 buffer.append(lineJoin); 213 buffer.append(", "); 214 buffer.append(lineCap); 215 buffer.append(", "); 216 buffer.append(miterLimit); 217 buffer.append(", "); 218 buffer.append(dashOffset); 219 buffer.append(", ["); 220 if (dashArray != null) { 221 buffer.append(dashArray); 222 } 223 buffer.append("]"); 224 return buffer.toString(); 225 } 226 } 227 228 /** 229 * @inheritDoc 230 */ 231 @Override public boolean equals(Object o) { 232 if (this == o) return true; 233 if ((this == NONE && o != NONE) || (o == NONE && this != NONE)) return false; 234 if (o == null || getClass() != o.getClass()) return false; 235 BorderStrokeStyle that = (BorderStrokeStyle) o; 236 if (this.hash != that.hash) return false; 237 if (Double.compare(that.dashOffset, dashOffset) != 0) return false; 238 if (Double.compare(that.miterLimit, miterLimit) != 0) return false; 239 if (!dashArray.equals(that.dashArray)) return false; 240 if (lineCap != that.lineCap) return false; 241 if (lineJoin != that.lineJoin) return false; 242 if (type != that.type) return false; 243 244 return true; 245 } 246 247 /** 248 * @inheritDoc 249 */ 250 @Override public int hashCode() { 251 return hash; 252 } 253 254 private static List<Double> asList(double... items) { 255 List<Double> list = new ArrayList<Double>(items.length); 256 for (int i=0; i<items.length; i++) { 257 list.add(items[i]); 258 } 259 return list; 260 } 261}