You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ColorUtil.java 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright 2000-2018 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.ui.components.colorpicker;
  17. import java.util.regex.Matcher;
  18. import java.util.regex.Pattern;
  19. import com.vaadin.shared.ui.colorpicker.Color;
  20. /**
  21. * Utility class for matching and parsing {@link Color} objects from
  22. * {@code String} input.
  23. *
  24. * Description of supported formats see
  25. * http://www.w3schools.com/cssref/css_colors_legal.asp
  26. *
  27. * @since
  28. */
  29. public class ColorUtil {
  30. private ColorUtil() {
  31. }
  32. /**
  33. * Parses {@link Color} from any of the following {@link String} inputs:
  34. * <br>
  35. * - RGB hex (e.g. "#FFAA00"), {@link #HEX_PATTERN}<br>
  36. * - RGB "function" (e.g. "rgb(128,0,255)"), {@link #RGB_PATTERN}<br>
  37. * - RGBA "function" (e.g. "rgba(50,50,50,0.2)"), {@link #RGBA_PATTERN}<br>
  38. * - HSL "function" (e.g. "hsl(50,50,50)"), {@link #HSL_PATTERN}<br>
  39. * - HSLA "function" (e.g. "hsl(50,50,50,0.2)"), {@link #HSLA_PATTERN}
  40. * <p>
  41. * Parsing is case-insensitive.
  42. *
  43. * @param input
  44. * String input
  45. * @return {@link Color} parsed from input
  46. * @throws NumberFormatException
  47. * Input does not match any recognized pattern
  48. */
  49. public static Color stringToColor(String input) {
  50. Matcher m = HEX_PATTERN.matcher(input);
  51. if (m.matches()) {
  52. return getHexPatternColor(m);
  53. }
  54. m = RGB_PATTERN.matcher(input);
  55. if (m.matches()) {
  56. return getRGBPatternColor(m);
  57. }
  58. m = RGBA_PATTERN.matcher(input);
  59. if (m.matches()) {
  60. return getRGBAPatternColor(m);
  61. }
  62. m = HSL_PATTERN.matcher(input);
  63. if (m.matches()) {
  64. return getHSLPatternColor(m);
  65. }
  66. m = HSLA_PATTERN.matcher(input);
  67. if (m.matches()) {
  68. return getHSLAPatternColor(m);
  69. }
  70. throw new NumberFormatException("Parsing color from input failed.");
  71. }
  72. /**
  73. * Parses {@link Color} from matched hexadecimal {@link Matcher}.
  74. *
  75. * @param matcher
  76. * {@link Matcher} matching hexadecimal pattern with named regex
  77. * groups {@code red}, {@code green}, and {@code blue}
  78. * @return {@link Color} parsed from {@link Matcher}
  79. */
  80. public static Color getHexPatternColor(Matcher matcher) {
  81. int red = Integer.parseInt(matcher.group("red"), 16);
  82. int green = Integer.parseInt(matcher.group("green"), 16);
  83. int blue = Integer.parseInt(matcher.group("blue"), 16);
  84. return new Color(red, green, blue);
  85. }
  86. /**
  87. * Parses {@link Color} from matched RGB {@link Matcher}.
  88. *
  89. * @param matcher
  90. * {@link Matcher} matching RGB pattern with named regex groups
  91. * {@code red}, {@code green}, and {@code blue}
  92. * @return {@link Color} parsed from {@link Matcher}
  93. */
  94. public static Color getRGBPatternColor(Matcher matcher) {
  95. int red = Integer.parseInt(matcher.group("red"));
  96. int green = Integer.parseInt(matcher.group("green"));
  97. int blue = Integer.parseInt(matcher.group("blue"));
  98. return new Color(red, green, blue);
  99. }
  100. /**
  101. * Parses {@link Color} from matched RGBA {@link Matcher}.
  102. *
  103. * @param matcher
  104. * {@link Matcher} matching RGBA pattern with named regex groups
  105. * {@code red}, {@code green}, {@code blue}, and {@code alpha}
  106. * @return {@link Color} parsed from {@link Matcher}
  107. */
  108. public static Color getRGBAPatternColor(Matcher matcher) {
  109. Color c = getRGBPatternColor(matcher);
  110. c.setAlpha((int) (Double.parseDouble(matcher.group("alpha")) * 255d));
  111. return c;
  112. }
  113. /**
  114. * Parses {@link Color} from matched HSL {@link Matcher}.
  115. *
  116. * @param matcher
  117. * {@link Matcher} matching HSL pattern with named regex groups
  118. * {@code hue}, {@code saturation}, and {@code light}
  119. * @return {@link Color} parsed from {@link Matcher}
  120. */
  121. public static Color getHSLPatternColor(Matcher matcher) {
  122. int hue = Integer.parseInt(matcher.group("hue"));
  123. int saturation = Integer.parseInt(matcher.group("saturation"));
  124. int light = Integer.parseInt(matcher.group("light"));
  125. int rgb = Color.HSLtoRGB(hue, saturation, light);
  126. return new Color(rgb);
  127. }
  128. /**
  129. * Parses {@link Color} from matched HSLA {@link Matcher}.
  130. *
  131. * @param matcher
  132. * {@link Matcher} matching HSLA pattern with named regex groups
  133. * {@code hue}, {@code saturation}, {@code light}, and
  134. * {@code alpha}
  135. * @return {@link Color} parsed from {@link Matcher}
  136. */
  137. public static Color getHSLAPatternColor(Matcher matcher) {
  138. Color c = getHSLPatternColor(matcher);
  139. c.setAlpha((int) (Double.parseDouble(matcher.group("alpha")) * 255d));
  140. return c;
  141. }
  142. /**
  143. * Case-insensitive {@link Pattern} with regular expression matching the
  144. * default hexadecimal color presentation pattern:<br>
  145. * '#' followed by six <code>[\da-fA-F]</code> characters.
  146. * <p>
  147. * Pattern contains named groups <code>red</code>, <code>green</code>, and
  148. * <code>blue</code>, which represent the individual values.
  149. */
  150. public static final Pattern HEX_PATTERN = Pattern.compile(
  151. "(?i)^#\\s*(?<red>[\\da-f]{2})(?<green>[\\da-f]{2})(?<blue>[\\da-f]{2}"
  152. + ")\\s*$");
  153. /**
  154. * Case-insensitive {@link Pattern} with regular expression matching common
  155. * RGB color presentation patterns:<br>
  156. * 'rgb' followed by three [0-255] number values. Values can be separated
  157. * with either comma or whitespace.
  158. * <p>
  159. * Pattern contains named groups <code>red</code>, <code>green</code>, and
  160. * <code>blue</code>, which represent the individual values.
  161. */
  162. public static final Pattern RGB_PATTERN = Pattern.compile(
  163. "(?i)^rgb\\(\\s*(?<red>[01]?\\d{1,2}|2[0-4]\\d|25[0-5])(?:\\s*[,+|\\"
  164. + "s+]\\s*)(?<green>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?:\\s*[,"
  165. + "+|\\s+]\\s*)(?<blue>[01]?\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\"
  166. + ")$");
  167. /**
  168. * Case-insensitive {@link Pattern} with regular expression matching common
  169. * RGBA presentation patterns:<br>
  170. * 'rgba' followed by three [0-255] values and one [0.0-1.0] value. Values
  171. * can be separated with either comma or whitespace. The only accepted
  172. * decimal marker is point ('.').
  173. * <p>
  174. * Pattern contains named groups <code>red</code>, <code>green</code>,
  175. * <code>blue</code>, and <code>alpha</code>, which represent the individual
  176. * values.
  177. */
  178. public static final Pattern RGBA_PATTERN = Pattern.compile(
  179. "(?i)^rgba\\(\\s*(?<red>[01]?\\d{1,2}|2[0-4]\\d|25[0-5])(?:\\s*[,+|"
  180. + "\\s+]\\s*)(?<green>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?:\\s"
  181. + "*[,+|\\s+]\\s*)(?<blue>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?"
  182. + ":\\s*[,+|\\s+]\\s*)(?<alpha>0(?:\\.\\d{1,2})?|0?(?:\\.\\"
  183. + "d{1,2})|1(?:\\.0{1,2})?)\\s*\\)$");
  184. /**
  185. * Case-insensitive {@link Pattern} with regular expression matching common
  186. * HSL presentation patterns:<br>
  187. * 'hsl' followed by one [0-360] value and two [0-100] percentage value.
  188. * Values can be separated with either comma or whitespace. The percent sign
  189. * ('%') is optional.
  190. * <p>
  191. * Pattern contains named groups <code>hue</code>,<code>saturation</code>,
  192. * and <code>light</code>, which represent the individual values.
  193. */
  194. public static final Pattern HSL_PATTERN = Pattern.compile(
  195. "(?i)hsl\\(\\s*(?<hue>[12]?\\d{1,2}|3[0-5]\\d|360)(?:\\s*[,+|\\s+]"
  196. + "\\s*)(?<saturation>\\d{1,2}|100)(?:\\s*%?\\s*[,+|\\s+]\\"
  197. + "s*)(?<light>\\d{1,2}|100)(?:\\s*%?\\s*)\\)$");
  198. /**
  199. * Case-insensitive {@link Pattern} with regular expression matching common
  200. * HSLA presentation patterns:<br>
  201. * 'hsla' followed by one [0-360] value, two [0-100] percentage values, and
  202. * one [0.0-1.0] value. Values can be separated with either comma or
  203. * whitespace. The percent sign ('%') is optional. The only accepted decimal
  204. * marker is point ('.').
  205. * <p>
  206. * Pattern contains named groups <code>hue</code>,<code>saturation</code>,
  207. * <code>light</code>, and <code>alpha</code>, which represent the
  208. * individual values.
  209. */
  210. public static final Pattern HSLA_PATTERN = Pattern.compile(
  211. "(?i)hsla\\(\\s*(?<hue>[12]?\\d{1,2}|3[0-5]\\d|360)(?:\\s*[,+|\\s+"
  212. + "]\\s*)(?<saturation>\\d{1,2}|100)(?:\\s*%?\\s*[,+|\\s+]\\s*"
  213. + ")(?<light>\\d{1,2}|100)(?:\\s*%?[,+|\\s+]\\s*)(?<alpha>"
  214. + "0(?:\\.\\d{1,2})?|0?(?:\\.\\d{1,2})|1(?:\\.0{1,2})?)"
  215. + "\\s*\\)$");
  216. }