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.

ExtendedColor.java 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.ss.usermodel;
  16. import java.util.Locale;
  17. /**
  18. * Represents a XSSF-style color (based on either a
  19. * {@link org.apache.poi.xssf.usermodel.XSSFColor} or a
  20. * {@link org.apache.poi.hssf.record.common.ExtendedColor}
  21. */
  22. public abstract class ExtendedColor implements Color {
  23. /**
  24. *
  25. * @param clr awt Color to set
  26. */
  27. protected void setColor(java.awt.Color clr) {
  28. setRGB(new byte[]{(byte)clr.getRed(), (byte)clr.getGreen(), (byte)clr.getBlue()});
  29. }
  30. /**
  31. * @return true if the color is automatic
  32. */
  33. public abstract boolean isAuto();
  34. /**
  35. * @return true if the color is indexed
  36. */
  37. public abstract boolean isIndexed();
  38. /**
  39. * @return true if the color is RGB / ARGB
  40. */
  41. public abstract boolean isRGB();
  42. /**
  43. * @return true if the color is from a Theme
  44. */
  45. public abstract boolean isThemed();
  46. /**
  47. * @return Indexed Color index value, if {@link #isIndexed()} is true
  48. */
  49. public abstract short getIndex();
  50. /**
  51. * @return Index of Theme color, if {@link #isThemed()} is true
  52. */
  53. public abstract int getTheme();
  54. /**
  55. * @return Standard Red Green Blue ctColor value (RGB) bytes.
  56. * If there was an A (Alpha) value, it will be stripped.
  57. */
  58. public abstract byte[] getRGB();
  59. /**
  60. * @return Standard Alpha Red Green Blue ctColor value (ARGB) bytes.
  61. */
  62. public abstract byte[] getARGB();
  63. /**
  64. * @return RGB or ARGB bytes or null
  65. */
  66. protected abstract byte[] getStoredRBG();
  67. /**
  68. * Sets the Red Green Blue or Alpha Red Green Blue
  69. * @param rgb bytes
  70. */
  71. public abstract void setRGB(byte[] rgb);
  72. /**
  73. * @return RGB or ARGB bytes, either stored or by index
  74. */
  75. protected byte[] getRGBOrARGB() {
  76. if (isIndexed() && getIndex() > 0) {
  77. byte[] rgb = getIndexedRGB();
  78. if (rgb != null) {
  79. return rgb;
  80. }
  81. }
  82. // Grab the colour
  83. return getStoredRBG();
  84. }
  85. /**
  86. * @return index color RGB bytes, if {@link #isIndexed()} == true, null if not indexed or index is invalid
  87. */
  88. protected abstract byte[] getIndexedRGB();
  89. /**
  90. * @return Standard Red Green Blue ctColor value (RGB) bytes with applied tint.
  91. * Alpha values are ignored.
  92. */
  93. public byte[] getRGBWithTint() {
  94. byte[] rgb = getStoredRBG();
  95. if (rgb != null) {
  96. if(rgb.length == 4) {
  97. byte[] tmp = new byte[3];
  98. System.arraycopy(rgb, 1, tmp, 0, 3);
  99. rgb = tmp;
  100. }
  101. double tint = getTint();
  102. for (int i = 0; i < rgb.length; i++){
  103. rgb[i] = applyTint(rgb[i] & 0xFF, tint);
  104. }
  105. }
  106. return rgb;
  107. }
  108. /**
  109. * @return the ARGB value in hex string format, eg FF00FF00.
  110. * Works for both regular and indexed colours.
  111. */
  112. public String getARGBHex() {
  113. byte[] rgb = getARGB();
  114. if(rgb == null) {
  115. return null;
  116. }
  117. StringBuilder sb = new StringBuilder();
  118. for(byte c : rgb) {
  119. int i = c & 0xff;
  120. String cs = Integer.toHexString(i);
  121. if(cs.length() == 1) {
  122. sb.append('0');
  123. }
  124. sb.append(cs);
  125. }
  126. return sb.toString().toUpperCase(Locale.ROOT);
  127. }
  128. /**
  129. * Sets the ARGB value from hex format, eg FF0077FF.
  130. * Only works for regular (non-indexed) colours
  131. * @param argb color ARGB hex string
  132. */
  133. public void setARGBHex(String argb) {
  134. if (argb.length() == 6 || argb.length() == 8) {
  135. byte[] rgb = new byte[argb.length()/2];
  136. for (int i=0; i<rgb.length; i++) {
  137. String part = argb.substring(i*2,(i+1)*2);
  138. rgb[i] = (byte)Integer.parseInt(part, 16);
  139. }
  140. setRGB(rgb);
  141. } else {
  142. throw new IllegalArgumentException("Must be of the form 112233 or FFEEDDCC");
  143. }
  144. }
  145. private static byte applyTint(int lum, double tint){
  146. if(tint > 0){
  147. return (byte)(lum * (1.0-tint) + (255 - 255 * (1.0-tint)));
  148. } else if (tint < 0){
  149. return (byte)(lum*(1+tint));
  150. } else {
  151. return (byte)lum;
  152. }
  153. }
  154. /**
  155. * Specifies the tint value applied to the ctColor.
  156. *
  157. * <p>
  158. * If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final
  159. * ctColor applied.
  160. * </p>
  161. * <p>
  162. * The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and
  163. * 1.0 means 100% lighten. Also, 0.0 means no change.
  164. * </p>
  165. * <p>
  166. * In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where
  167. * HLSMAX is currently 255.
  168. * </p>
  169. * Here are some examples of how to apply tint to ctColor:
  170. * <blockquote>
  171. * <pre>
  172. * If (tint &lt; 0)
  173. * Lum' = Lum * (1.0 + tint)
  174. *
  175. * For example: Lum = 200; tint = -0.5; Darken 50%
  176. * Lum' = 200 * (0.5) =&gt; 100
  177. * For example: Lum = 200; tint = -1.0; Darken 100% (make black)
  178. * Lum' = 200 * (1.0-1.0) =&gt; 0
  179. * If (tint &gt; 0)
  180. * Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint))
  181. * For example: Lum = 100; tint = 0.75; Lighten 75%
  182. *
  183. * Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75))
  184. * = 100 * .25 + (255 - 255 * .25)
  185. * = 25 + (255 - 63) = 25 + 192 = 217
  186. * For example: Lum = 100; tint = 1.0; Lighten 100% (make white)
  187. * Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1))
  188. * = 100 * 0 + (255 - 255 * 0)
  189. * = 0 + (255 - 0) = 255
  190. * </pre>
  191. * </blockquote>
  192. *
  193. * @return the tint value
  194. */
  195. public abstract double getTint();
  196. /**
  197. * Specifies the tint value applied to the ctColor.
  198. *
  199. * <p>
  200. * If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final
  201. * ctColor applied.
  202. * </p>
  203. * <p>
  204. * The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and
  205. * 1.0 means 100% lighten. Also, 0.0 means no change.
  206. * </p>
  207. * <p>
  208. * In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where
  209. * HLSMAX is currently 255.
  210. * </p>
  211. * Here are some examples of how to apply tint to ctColor:
  212. * <blockquote>
  213. * <pre>
  214. * If (tint &lt; 0)
  215. * Lum' = Lum * (1.0 + tint)
  216. *
  217. * For example: Lum = 200; tint = -0.5; Darken 50%
  218. * Lum' = 200 * (0.5) =&gt; 100
  219. * For example: Lum = 200; tint = -1.0; Darken 100% (make black)
  220. * Lum' = 200 * (1.0-1.0) =&gt; 0
  221. * If (tint &gt; 0)
  222. * Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint))
  223. * For example: Lum = 100; tint = 0.75; Lighten 75%
  224. *
  225. * Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75))
  226. * = 100 * .25 + (255 - 255 * .25)
  227. * = 25 + (255 - 63) = 25 + 192 = 217
  228. * For example: Lum = 100; tint = 1.0; Lighten 100% (make white)
  229. * Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1))
  230. * = 100 * 0 + (255 - 255 * 0)
  231. * = 0 + (255 - 0) = 255
  232. * </pre>
  233. * </blockquote>
  234. *
  235. * @param tint the tint value
  236. */
  237. public abstract void setTint(double tint);
  238. }