Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

ColorUtil.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. package com.vaadin.sass.util;
  2. import org.w3c.css.sac.LexicalUnit;
  3. import com.vaadin.sass.parser.LexicalUnitImpl;
  4. public class ColorUtil {
  5. public static LexicalUnitImpl hexColorToHsl(LexicalUnitImpl hexColor) {
  6. String s = hexColor.getStringValue().substring(1);
  7. int r = 0, g = 0, b = 0;
  8. if (s.length() == 3) {
  9. String sh = s.substring(0, 1);
  10. r = Integer.parseInt(sh + sh, 16);
  11. sh = s.substring(1, 2);
  12. g = Integer.parseInt(sh + sh, 16);
  13. sh = s.substring(2, 3);
  14. b = Integer.parseInt(sh + sh, 16);
  15. } else if (s.length() == 6) {
  16. r = Integer.parseInt(s.substring(0, 2), 16);
  17. g = Integer.parseInt(s.substring(2, 4), 16);
  18. b = Integer.parseInt(s.substring(4, 6), 16);
  19. }
  20. int hsl[] = calculateHsl(r, g, b);
  21. LexicalUnitImpl hslParams = createHslParameters(hsl[0], hsl[1], hsl[2],
  22. hexColor.getLineNumber(), hexColor.getColumnNumber(),
  23. (LexicalUnitImpl) hexColor.getPreviousLexicalUnit());
  24. return LexicalUnitImpl.createFunction(hexColor.getLineNumber(),
  25. hexColor.getColumnNumber(),
  26. (LexicalUnitImpl) hexColor.getPreviousLexicalUnit(), "hsl",
  27. hslParams);
  28. }
  29. public static LexicalUnitImpl hslToHexColor(LexicalUnitImpl hsl, int lengh) {
  30. int[] rgb = calculateRgb(hsl);
  31. StringBuilder builder = new StringBuilder("#");
  32. for (int i = 0; i < 3; i++) {
  33. String color = Integer.toHexString(rgb[i]);
  34. if (lengh == 3) {
  35. if (color.length() == 1) {
  36. color = "0" + color;
  37. }
  38. }
  39. if (lengh == 6) {
  40. color = color.substring(0, 1);
  41. }
  42. builder.append(color);
  43. }
  44. return LexicalUnitImpl.createIdent(hsl.getLineNumber(),
  45. hsl.getColumnNumber(),
  46. (LexicalUnitImpl) hsl.getPreviousLexicalUnit(),
  47. builder.toString());
  48. }
  49. private static int[] calculateRgb(LexicalUnitImpl hsl) {
  50. LexicalUnitImpl hslParam = hsl.getParameters();
  51. LexicalUnitImpl hue = null;
  52. LexicalUnitImpl saturation = null;
  53. LexicalUnitImpl lightness = null;
  54. int i = 0;
  55. while (i < 5) {
  56. switch (i) {
  57. case 0:
  58. hue = hslParam;
  59. break;
  60. case 2:
  61. saturation = hslParam;
  62. break;
  63. case 4:
  64. lightness = hslParam;
  65. break;
  66. case 1:
  67. case 3:
  68. break;
  69. }
  70. hslParam = (LexicalUnitImpl) hslParam.getNextLexicalUnit();
  71. i++;
  72. }
  73. float h = ((hue.getFloatValue() % 360) + 360) % 360 / 360;
  74. float s = saturation.getFloatValue() / 100;
  75. float l = lightness.getFloatValue() / 100;
  76. float m2, m1;
  77. int[] rgb = new int[3];
  78. m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
  79. m1 = l * 2 - m2;
  80. rgb[0] = Math.round(hueToRgb(m1, m2, h + 1f / 3) * 255);
  81. rgb[1] = Math.round(hueToRgb(m1, m2, h) * 255);
  82. rgb[2] = Math.round(hueToRgb(m1, m2, h - 1f / 3) * 255);
  83. return rgb;
  84. }
  85. public static LexicalUnitImpl rgbToHsl(LexicalUnitImpl rgb) {
  86. LexicalUnitImpl rgbParam = rgb.getParameters();
  87. LexicalUnitImpl red = null;
  88. LexicalUnitImpl green = null;
  89. LexicalUnitImpl blue = null;
  90. int i = 0;
  91. while (i < 5) {
  92. switch (i) {
  93. case 0:
  94. red = rgbParam;
  95. break;
  96. case 2:
  97. green = rgbParam;
  98. break;
  99. case 4:
  100. blue = rgbParam;
  101. break;
  102. case 1:
  103. case 3:
  104. break;
  105. }
  106. rgbParam = (LexicalUnitImpl) rgbParam.getNextLexicalUnit();
  107. i++;
  108. }
  109. int hsl[] = calculateHsl(red.getIntegerValue(),
  110. green.getIntegerValue(), blue.getIntegerValue());
  111. rgbParam = rgb.getParameters();
  112. LexicalUnitImpl hslParams = createHslParameters(hsl[0], hsl[1], hsl[2],
  113. rgbParam.getLineNumber(), rgbParam.getColumnNumber(),
  114. (LexicalUnitImpl) rgbParam.getPreviousLexicalUnit());
  115. return LexicalUnitImpl.createFunction(rgb.getLineNumber(),
  116. rgb.getColumnNumber(),
  117. (LexicalUnitImpl) rgb.getPreviousLexicalUnit(), "hsl",
  118. hslParams);
  119. }
  120. private static int[] calculateHsl(int red, int green, int blue) {
  121. int[] hsl = new int[3];
  122. float r = red / 255f;
  123. float g = green / 255f;
  124. float b = blue / 255f;
  125. float max = Math.max(Math.max(r, g), b);
  126. float min = Math.min(Math.min(r, g), b);
  127. float d = max - min;
  128. float h = 0f, s = 0f, l = 0f;
  129. if (max == min) {
  130. h = 0;
  131. }
  132. if (max == r) {
  133. h = 60 * (g - b) / d;
  134. } else if (max == g) {
  135. h = 60 * (b - r) / d + 120;
  136. } else if (max == b) {
  137. h = 60 * (r - g) / d + 240;
  138. }
  139. l = (max + min) / 2f;
  140. if (max == min) {
  141. s = 0;
  142. } else if (l < 0.5) {
  143. s = d / (2 * l);
  144. } else {
  145. s = d / (2 - 2 * l);
  146. }
  147. hsl[0] = Math.round(h % 360);
  148. hsl[1] = Math.round(s * 100);
  149. hsl[2] = Math.round(l * 100);
  150. return hsl;
  151. }
  152. public static LexicalUnitImpl hslToRgb(LexicalUnitImpl hsl) {
  153. int[] rgb = calculateRgb(hsl);
  154. LexicalUnitImpl hslParam = hsl.getParameters();
  155. LexicalUnitImpl rgbParams = createRgbParameters(rgb[0], rgb[1], rgb[2],
  156. hslParam.getLineNumber(), hslParam.getColumnNumber(),
  157. (LexicalUnitImpl) hslParam.getPreviousLexicalUnit());
  158. return LexicalUnitImpl.createFunction(hsl.getLineNumber(),
  159. hsl.getColumnNumber(),
  160. (LexicalUnitImpl) hsl.getPreviousLexicalUnit(), "rgb",
  161. rgbParams);
  162. }
  163. private static float hueToRgb(float m1, float m2, float h) {
  164. if (h < 0) {
  165. h = h + 1;
  166. }
  167. if (h > 1) {
  168. h = h - 1;
  169. }
  170. if (h * 6 < 1) {
  171. return m1 + (m2 - m1) * h * 6;
  172. }
  173. if (h * 2 < 1) {
  174. return m2;
  175. }
  176. if (h * 3 < 2) {
  177. return m1 + (m2 - m1) * (2f / 3 - h) * 6;
  178. }
  179. return m1;
  180. }
  181. private static LexicalUnitImpl createRgbParameters(int r, int g, int b,
  182. int ln, int cn, LexicalUnitImpl prev) {
  183. LexicalUnitImpl red = LexicalUnitImpl.createInteger(ln, cn, prev, r);
  184. LexicalUnitImpl firstComma = LexicalUnitImpl.createComma(ln, cn, red);
  185. LexicalUnitImpl green = LexicalUnitImpl.createInteger(ln, cn,
  186. firstComma, g);
  187. LexicalUnitImpl secondComma = LexicalUnitImpl
  188. .createComma(ln, cn, green);
  189. LexicalUnitImpl.createInteger(ln, cn, secondComma, b);
  190. return red;
  191. }
  192. private static LexicalUnitImpl createHslParameters(int h, int s, int l,
  193. int ln, int cn, LexicalUnitImpl prev) {
  194. LexicalUnitImpl hue = LexicalUnitImpl.createInteger(ln, cn, prev, h);
  195. LexicalUnitImpl firstComma = LexicalUnitImpl.createComma(ln, cn, hue);
  196. LexicalUnitImpl saturation = LexicalUnitImpl.createPercentage(ln, cn,
  197. firstComma, s);
  198. LexicalUnitImpl secondComma = LexicalUnitImpl.createComma(ln, cn,
  199. saturation);
  200. LexicalUnitImpl.createPercentage(ln, cn, secondComma, l);
  201. return hue;
  202. }
  203. public static LexicalUnitImpl darken(LexicalUnitImpl darkenFunc) {
  204. LexicalUnitImpl color = darkenFunc.getParameters();
  205. LexicalUnit amount = color.getNextLexicalUnit().getNextLexicalUnit();
  206. LexicalUnitImpl pre = (LexicalUnitImpl) darkenFunc
  207. .getPreviousLexicalUnit();
  208. return adjust(color, amount, ColorOperation.Darken, pre);
  209. }
  210. private static LexicalUnitImpl adjust(LexicalUnitImpl color,
  211. LexicalUnit amount, ColorOperation op, LexicalUnitImpl pre) {
  212. if (color.getLexicalUnitType() == LexicalUnit.SAC_FUNCTION) {
  213. LexicalUnit funcParam = color.getParameters();
  214. if ("hsl".equals(color.getFunctionName())) {
  215. LexicalUnit lightness = funcParam;
  216. for (int index = 0; index < 4; index++) {
  217. lightness = lightness.getNextLexicalUnit();
  218. }
  219. float newValue = 0f;
  220. if (op == ColorOperation.Darken) {
  221. newValue = lightness.getFloatValue()
  222. - amount.getFloatValue();
  223. newValue = newValue < 0 ? 0 : newValue;
  224. } else if (op == ColorOperation.Lighten) {
  225. newValue = lightness.getFloatValue()
  226. + amount.getFloatValue();
  227. newValue = newValue > 100 ? 100 : newValue;
  228. }
  229. ((LexicalUnitImpl) lightness).setFloatValue(newValue);
  230. return LexicalUnitImpl.createFunction(color.getLineNumber(),
  231. color.getColumnNumber(), pre, color.getFunctionName(),
  232. funcParam);
  233. }
  234. } else if (color.getLexicalUnitType() == LexicalUnit.SAC_IDENT) {
  235. if (color.getStringValue().startsWith("#")) {
  236. return hslToHexColor(
  237. adjust(hexColorToHsl(color), amount, op, pre), color
  238. .getStringValue().substring(1).length());
  239. }
  240. } else if (color.getLexicalUnitType() == LexicalUnit.SAC_RGBCOLOR) {
  241. LexicalUnitImpl hsl = rgbToHsl(color);
  242. LexicalUnitImpl hslAfterDarken = adjust(hsl, amount, op, pre);
  243. return hslToRgb(hslAfterDarken);
  244. }
  245. return color;
  246. }
  247. public static LexicalUnitImpl lighten(LexicalUnitImpl lightenFunc) {
  248. LexicalUnitImpl color = lightenFunc.getParameters();
  249. LexicalUnit amount = color.getNextLexicalUnit().getNextLexicalUnit();
  250. LexicalUnitImpl pre = (LexicalUnitImpl) lightenFunc
  251. .getPreviousLexicalUnit();
  252. return adjust(color, amount, ColorOperation.Lighten, pre);
  253. }
  254. enum ColorOperation {
  255. Darken, Lighten
  256. }
  257. }