Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 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.paint; 027 028import com.sun.javafx.beans.annotations.Default; 029 030import java.util.ArrayList; 031import java.util.Arrays; 032import java.util.Collections; 033import java.util.List; 034 035/** 036 * Defines one element of the ramp of colors to use on a gradient. 037 * For more information see {@code javafx.scene.paint.LinearGradient} and 038 * {@code javafx.scene.paint.RadialGradient}. 039 * 040 * <p>Example:</p> 041 * <pre><code> 042 * // object bounding box relative (proportional:true, default) 043 * Stop[] stops = { new Stop(0, Color.WHITE), new Stop(1, Color.BLACK)}; 044 * LinearGradient lg = new LinearGradient(0, 0, 1, 0, true, CycleMethod.No_CYCLE, stops); 045 * Rectangle r = new Rectangle(); 046 * r.setFill(lg); 047 *</code></pre> 048 */ 049public final class Stop { 050 051 static final List<Stop> NO_STOPS = 052 Collections.unmodifiableList(Arrays.asList( 053 new Stop(0.0, Color.TRANSPARENT), 054 new Stop(1.0, Color.TRANSPARENT) 055 )); 056 057 static List<Stop> normalize(Stop stops[]) { 058 List<Stop> stoplist = (stops == null ? null : Arrays.asList(stops)); 059 return normalize(stoplist); 060 } 061 062 static List<Stop> normalize(List<Stop> stops) { 063 if (stops == null) { 064 return NO_STOPS; 065 } 066 Stop zerostop = null; 067 Stop onestop = null; 068 List<Stop> newlist = new ArrayList<Stop>(stops.size()); 069 for (Stop s : stops) { 070 if (s == null || s.getColor() == null) continue; 071 double off = s.getOffset(); 072 if (off <= 0.0) { 073 if (zerostop == null || off >= zerostop.getOffset()) { 074 zerostop = s; 075 } 076 } else if (off >= 1.0) { 077 if (onestop == null || off < onestop.getOffset()) { 078 onestop = s; 079 } 080 } else if (off == off) { // non-NaN 081 for (int i = newlist.size() - 1; i >= 0; i--) { 082 Stop s2 = newlist.get(i); 083 if (s2.getOffset() <= off) { 084 if (s2.getOffset() == off) { 085 if (i > 0 && newlist.get(i-1).getOffset() == off) { 086 newlist.set(i, s); 087 } else { 088 newlist.add(i+1, s); 089 } 090 } else { 091 newlist.add(i+1, s); 092 } 093 s = null; 094 break; 095 } 096 } 097 if (s != null) { 098 newlist.add(0, s); 099 } 100 } 101 } 102 103 if (zerostop == null) { 104 Color zerocolor; 105 if (newlist.isEmpty()) { 106 if (onestop == null) { 107 return NO_STOPS; 108 } 109 zerocolor = onestop.getColor(); 110 } else { 111 zerocolor = newlist.get(0).getColor(); 112 if (onestop == null && newlist.size() == 1) { 113 // Special case for a single color with a non-0,1 offset. 114 // If we leave the color in there we end up with a 3-color 115 // gradient with all the colors being identical and we 116 // will not catch the optimization to a solid color. 117 newlist.clear(); 118 } 119 } 120 zerostop = new Stop(0.0, zerocolor); 121 } else if (zerostop.getOffset() < 0.0) { 122 zerostop = new Stop(0.0, zerostop.getColor()); 123 } 124 newlist.add(0, zerostop); 125 126 if (onestop == null) { 127 onestop = new Stop(1.0, newlist.get(newlist.size()-1).getColor()); 128 } else if (onestop.getOffset() > 1.0) { 129 onestop = new Stop(1.0, onestop.getColor()); 130 } 131 newlist.add(onestop); 132 133 return Collections.unmodifiableList(newlist); 134 } 135 136 /** 137 * The {@code offset} variable is a number ranging from {@code 0} to {@code 1} 138 * that indicates where this gradient stop is placed. For linear gradients, 139 * the {@code offset} variable represents a location along the gradient vector. 140 * For radial gradients, it represents a percentage distance from 141 * the focus point to the edge of the outermost/largest circle. 142 * 143 * @profile common 144 * @defaultValue 0.0 145 */ 146 private double offset; 147 148 /** 149 * Gets a number ranging from {@code 0} to {@code 1} 150 * that indicates where this gradient stop is placed. For linear gradients, 151 * the {@code offset} variable represents a location along the gradient vector. 152 * For radial gradients, it represents a percentage distance from 153 * the focus point to the edge of the outermost/largest circle. 154 * 155 * @return position of the Stop within the gradient 156 * (ranging from {@code 0} to {@code 1}) 157 */ 158 public final double getOffset() { 159 return offset; 160 } 161 162 /** 163 * The color of the gradient at this offset. 164 * 165 * @profile common 166 * @defaultValue Color.BLACK 167 */ 168 private Color color; 169 170 /** 171 * Gets the color of the gradient at this offset. 172 * @return the color of the gradient at this offset 173 */ 174 public final Color getColor() { 175 return color; 176 } 177 178 /** 179 * The cached hash code, used to improve performance in situations where 180 * we cache gradients, such as in the CSS routines. 181 */ 182 private int hash = 0; 183 184 /** 185 * Creates a new instance of Stop. 186 * @param offset Stop's position (ranging from {@code 0} to {@code 1} 187 * @param color Stop's color 188 */ 189 public Stop(double offset, @Default("javafx.scene.paint.Color.BLACK") Color color) { 190 this.offset = offset; 191 this.color = color; 192 } 193 194 /** 195 * Indicates whether some other object is "equal to" this one. 196 * @param obj the reference object with which to compare. 197 * @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise. 198 */ 199 @Override public boolean equals(Object obj) { 200 if (obj == null) return false; 201 if (obj == this) return true; 202 if (obj instanceof Stop) { 203 Stop other = (Stop) obj; 204 return offset == other.offset && 205 (color == null ? other.color == null : color.equals(other.color)); 206 } else return false; 207 } 208 209 /** 210 * Returns a hash code for this {@code Stop} object. 211 * @return a hash code for this {@code Stop} object. 212 */ 213 @Override public int hashCode() { 214 if (hash == 0) { 215 long bits = 17L; 216 bits = 37L * bits + Double.doubleToLongBits(offset); 217 bits = 37L * bits + color.hashCode(); 218 hash = (int) (bits ^ (bits >> 32)); 219 } 220 return hash; 221 } 222 223 /** 224 * Returns a string representation of this {@code Stop} object. 225 * @return a string representation of this {@code Stop} object. 226 */ 227 @Override public String toString() { 228 return color + " " + offset*100 + "%"; 229 } 230}