PageRenderTime 48ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/javafx-ui-common/src/com/sun/javafx/scene/paint/GradientUtils.java

https://bitbucket.org/rbair/rbair-controls-8
Java | 306 lines | 229 code | 40 blank | 37 comment | 61 complexity | c9afeb3e7afa91266b895ab06837dcdc MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
  1. /*
  2. * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  10. *
  11. * This code is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * version 2 for more details (a copy is included in the LICENSE file that
  15. * accompanied this code).
  16. *
  17. * You should have received a copy of the GNU General Public License version
  18. * 2 along with this work; if not, write to the Free Software Foundation,
  19. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22. * or visit www.oracle.com if you need additional information or have any
  23. * questions.
  24. */
  25. package com.sun.javafx.scene.paint;
  26. import java.util.LinkedList;
  27. import java.util.List;
  28. import javafx.scene.paint.Color;
  29. import javafx.scene.paint.Stop;
  30. public class GradientUtils {
  31. public static String lengthToString(double value, boolean proportional) {
  32. if (proportional) {
  33. return (value * 100) + "%";
  34. } else {
  35. return value + "px";
  36. }
  37. }
  38. public static class Point {
  39. public static final Point MIN = new Point(0, true);
  40. public static final Point MAX = new Point(1, true);
  41. public double value;
  42. public boolean proportional;
  43. @Override
  44. public String toString() {
  45. return "value = " + value + ", proportional = " + proportional;
  46. }
  47. public Point(double value, boolean proportional) {
  48. this.value = value;
  49. this.proportional = proportional;
  50. }
  51. public Point() {
  52. }
  53. }
  54. public static class Parser {
  55. private int index;
  56. private String[] tokens;
  57. private boolean proportional;
  58. private boolean proportionalSet = false;
  59. private interface Delimiter {
  60. public boolean isDelimiter(char value);
  61. }
  62. private String[] splitString(String string, Delimiter delimiter, boolean canRepeat) {
  63. List<String> tokenList = new LinkedList<String>();
  64. StringBuilder token = new StringBuilder();
  65. int i = 0;
  66. char[] input = string.toCharArray();
  67. while (i < input.length) {
  68. char currentChar = input[i];
  69. if (delimiter.isDelimiter(currentChar)) {
  70. if (!canRepeat || token.length() > 0) {
  71. tokenList.add(token.toString());
  72. }
  73. token.setLength(0);
  74. } else if (currentChar == '(') {
  75. while (i < input.length) {
  76. token.append(input[i]);
  77. if (input[i] == ')') {
  78. break;
  79. }
  80. i++;
  81. }
  82. } else {
  83. token.append(input[i]);
  84. }
  85. i++;
  86. }
  87. if (!canRepeat || token.length() > 0) {
  88. tokenList.add(token.toString());
  89. }
  90. return tokenList.toArray(new String[tokenList.size()]);
  91. }
  92. public Parser(String content) {
  93. tokens = splitString(content, new Delimiter() {
  94. @Override
  95. public boolean isDelimiter(char value) {
  96. return (value == ',');
  97. }
  98. }, false);
  99. index = 0;
  100. }
  101. public int getSize() {
  102. return tokens.length;
  103. }
  104. public void shift() {
  105. index++;
  106. }
  107. public String getCurrentToken() {
  108. String currentToken = tokens[index].trim();
  109. if (currentToken.isEmpty()) {
  110. throw new IllegalArgumentException("Invalid gradient specification: "
  111. + "found empty token.");
  112. }
  113. return currentToken;
  114. }
  115. public String[] splitCurrentToken() {
  116. return getCurrentToken().split("\\s");
  117. }
  118. public static void checkNumberOfArguments(String[] tokens, int count) {
  119. if (tokens.length < count + 1) {
  120. throw new IllegalArgumentException("Invalid gradient specification: "
  121. + "parameter '"+ tokens[0] + "' needs " + count + " argument(s).");
  122. }
  123. }
  124. public static double parseAngle(String value) {
  125. double angle = 0;
  126. if (value.endsWith("deg")) {
  127. value = value.substring(0, value.length() - 3);
  128. angle = Double.parseDouble(value);
  129. } else if (value.endsWith("grad")) {
  130. value = value.substring(0, value.length() - 4);
  131. angle = Double.parseDouble(value);
  132. angle = angle * 9 / 10;
  133. } else if (value.endsWith("rad")) {
  134. value = value.substring(0, value.length() - 3);
  135. angle = Double.parseDouble(value);
  136. angle = angle * 180 / Math.PI;
  137. } else if (value.endsWith("turn")) {
  138. value = value.substring(0, value.length() - 4);
  139. angle = Double.parseDouble(value);
  140. angle = angle * 360;
  141. } else {
  142. throw new IllegalArgumentException("Invalid gradient specification:"
  143. + "angle must end in deg, rad, grad, or turn");
  144. }
  145. return angle;
  146. }
  147. public static double parsePercentage(String value) {
  148. double percentage;
  149. if (value.endsWith("%")) {
  150. value = value.substring(0, value.length() - 1);
  151. percentage = Double.parseDouble(value) / 100;
  152. } else {
  153. throw new IllegalArgumentException("Invalid gradient specification: "
  154. + "focus-distance must be specified as percentage");
  155. }
  156. return percentage;
  157. }
  158. public Point parsePoint(String value) {
  159. Point p = new Point();
  160. if (value.endsWith("%")) {
  161. p.proportional = true;
  162. value = value.substring(0, value.length() - 1);
  163. } else if (value.endsWith("px")) {
  164. value = value.substring(0, value.length() - 2);
  165. }
  166. p.value = Double.parseDouble(value);
  167. if (p.proportional) {
  168. p.value /= 100;
  169. }
  170. if (proportionalSet && proportional != p.proportional) {
  171. throw new IllegalArgumentException("Invalid gradient specification:"
  172. + "cannot mix proportional and non-proportional values");
  173. }
  174. proportionalSet = true;
  175. proportional = p.proportional;
  176. return p;
  177. }
  178. // length specifies the length of gradient line used when recalculating
  179. // non-proportional color-stops
  180. public Stop[] parseStops(boolean proportional, double length) {
  181. int stopsCount = tokens.length - index;
  182. Color[] colors = new Color[stopsCount];
  183. double[] offsets = new double[stopsCount];
  184. Stop[] stops = new Stop[stopsCount];
  185. for (int i = 0; i < stopsCount; i++) {
  186. String stopString = tokens[i + index].trim();
  187. String[] stopTokens = splitString(stopString, new Delimiter() {
  188. @Override
  189. public boolean isDelimiter(char value) {
  190. return Character.isWhitespace(value);
  191. }
  192. }, true);
  193. if (stopTokens.length == 0) {
  194. throw new IllegalArgumentException("Invalid gradient specification, "
  195. + "empty stop found");
  196. }
  197. String currentToken = stopTokens[0];
  198. double offset = -1;
  199. Color c = Color.web(currentToken);
  200. if (stopTokens.length == 2) {
  201. // parsing offset
  202. String o = stopTokens[1];
  203. if (o.endsWith("%")) {
  204. o = o.substring(0, o.length() - 1);
  205. offset = Double.parseDouble(o) / 100;
  206. } else if (!proportional) {
  207. if (o.endsWith("px")) {
  208. o = o.substring(0, o.length() - 2);
  209. }
  210. offset = Double.parseDouble(o) / length;
  211. } else {
  212. throw new IllegalArgumentException("Invalid gradient specification, "
  213. + "non-proportional stops not permited in proportional gradient: " + o);
  214. }
  215. } else if (stopTokens.length > 2) {
  216. throw new IllegalArgumentException("Invalid gradient specification, "
  217. + "unexpected content in stop specification: " + stopTokens[2]);
  218. }
  219. colors[i] = c;
  220. offsets[i] = offset;
  221. }
  222. // normalize based on CSS specification
  223. // If the first color-stop does not have a position, set its position to 0%.
  224. // If the last color-stop does not have a position, set its position to 100%.
  225. if (offsets[0] < 0) {
  226. offsets[0] = 0;
  227. }
  228. if (offsets[offsets.length - 1] < 0) {
  229. offsets[offsets.length - 1] = 1;
  230. }
  231. // If a color-stop has a position that is less than the specified position
  232. // of any color-stop before it in the list, set its position to be equal
  233. // to the largest specified position of any color-stop before it.
  234. double max = offsets[0];
  235. for (int i = 1; i < offsets.length; i++) {
  236. if (offsets[i] < max && offsets[i] > 0) {
  237. offsets[i] = max;
  238. } else {
  239. max = offsets[i];
  240. }
  241. }
  242. // If any color-stop still does not have a position, then,
  243. // for each run of adjacent color-stops without positions,
  244. // set their positions so that they are evenly spaced
  245. // between the preceding and following color-stops with positions.
  246. int firstIndex = -1;
  247. for (int i = 1; i < offsets.length; i++) {
  248. double offset = offsets[i];
  249. if (offset < 0 && firstIndex < 0) {
  250. firstIndex = i;
  251. } else if (offset >= 0 && firstIndex > 0) {
  252. int n = i - firstIndex + 1;
  253. double part = (offsets[i] - offsets[firstIndex - 1]) / n;
  254. for (int j = 0; j < n - 1; j++) {
  255. offsets[firstIndex + j] = offsets[firstIndex - 1] + part * (j + 1);
  256. }
  257. }
  258. }
  259. for (int i = 0; i < stops.length; i++) {
  260. Stop stop = new Stop(offsets[i], colors[i]);
  261. stops[i] = stop;
  262. }
  263. return stops;
  264. }
  265. }
  266. }