1. /*
  2. * @(#)Color.java 1.66 00/02/02
  3. *
  4. * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.awt;
  11. import java.io.*;
  12. import java.lang.*;
  13. import java.awt.image.ColorModel;
  14. import java.awt.geom.AffineTransform;
  15. import java.awt.geom.Rectangle2D;
  16. import java.awt.color.ColorSpace;
  17. /**
  18. * The <code>Color</code> class is used encapsulate colors in the default
  19. * sRGB color space or colors in arbitrary color spaces identified by a
  20. * {@link ColorSpace}. Every color has an implicit alpha value of 1.0 or
  21. * an explicit one provided in the constructor. The alpha value
  22. * defines the transparency of a color and can be represented by
  23. * a float value in the range 0.0 - 1.0 or 0 - 255.
  24. * An alpha value of 1.0 or 255 means that the color is completely
  25. * opaque and an alpha value of 0 or 0.0 means that the color is
  26. * completely transparent.
  27. * When constructing a <code>Color</code> with an explicit alpha or
  28. * getting the color/alpha components of a <code>Color</code>, the color
  29. * components are never premultiplied by the alpha component.
  30. * <p>
  31. * The default color space for the Java 2D(tm) API is sRGB, a proposed
  32. * standard RGB color space. For further information on sRGB,
  33. * see <A href="http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
  34. * http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
  35. * </A>.
  36. * <p>
  37. * @version 10 Feb 1997
  38. * @author Sami Shaio
  39. * @author Arthur van Hoff
  40. * @see ColorSpace
  41. * @see AlphaComposite
  42. */
  43. public class Color implements Paint, java.io.Serializable {
  44. /**
  45. * The color white. In the default sRGB space.
  46. */
  47. public final static Color white = new Color(255, 255, 255);
  48. /**
  49. * The color light gray. In the default sRGB space.
  50. */
  51. public final static Color lightGray = new Color(192, 192, 192);
  52. /**
  53. * The color gray. In the default sRGB space.
  54. */
  55. public final static Color gray = new Color(128, 128, 128);
  56. /**
  57. * The color dark gray. In the default sRGB space.
  58. */
  59. public final static Color darkGray = new Color(64, 64, 64);
  60. /**
  61. * The color black. In the default sRGB space.
  62. */
  63. public final static Color black = new Color(0, 0, 0);
  64. /**
  65. * The color red. In the default sRGB space.
  66. */
  67. public final static Color red = new Color(255, 0, 0);
  68. /**
  69. * The color pink. In the default sRGB space.
  70. */
  71. public final static Color pink = new Color(255, 175, 175);
  72. /**
  73. * The color orange. In the default sRGB space.
  74. */
  75. public final static Color orange = new Color(255, 200, 0);
  76. /**
  77. * The color yellow. In the default sRGB space.
  78. */
  79. public final static Color yellow = new Color(255, 255, 0);
  80. /**
  81. * The color green. In the default sRGB space.
  82. */
  83. public final static Color green = new Color(0, 255, 0);
  84. /**
  85. * The color magenta. In the default sRGB space.
  86. */
  87. public final static Color magenta = new Color(255, 0, 255);
  88. /**
  89. * The color cyan. In the default sRGB space.
  90. */
  91. public final static Color cyan = new Color(0, 255, 255);
  92. /**
  93. * The color blue. In the default sRGB space.
  94. */
  95. public final static Color blue = new Color(0, 0, 255);
  96. /**
  97. * Private data.
  98. */
  99. transient private long pData;
  100. /**
  101. * The color value.
  102. * @serial
  103. * @see #getRGB
  104. */
  105. int value;
  106. /**
  107. * The color value in the default sRGB <code>ColorSpace</code> as
  108. * <code>float</code> components (no alpha).
  109. * If <code>null</code> after object construction, this must be an
  110. * sRGB color constructed with 8-bit precision, so compute from the
  111. * <code>int</code> color value.
  112. * @serial
  113. * @see #getRGBColorComponents
  114. * @see #getRGBComponents
  115. */
  116. private float frgbvalue[] = null;
  117. /**
  118. * The color value in the native <code>ColorSpace</code> as
  119. * <code>float</code> components (no alpha).
  120. * If <code>null</code> after object construction, this must be an
  121. * sRGB color constructed with 8-bit precision, so compute from the
  122. * <code>int</code> color value.
  123. * @serial
  124. * @see #getRGBColorComponents
  125. * @see #getRGBComponents
  126. */
  127. private float fvalue[] = null;
  128. /**
  129. * The alpha value as a <code>float</code> component.
  130. * If <code>frgbvalue</code> is <code>null</code>, this is not valid
  131. * data, so compute from the <code>int</code> color value.
  132. * @serial
  133. * @see #getRGBComponents
  134. * @see #getComponents
  135. */
  136. private float falpha = 0.0f;
  137. /**
  138. * The <code>ColorSpace</code>. If <code>null</code>, then it's
  139. * default is sRGB.
  140. * @serial
  141. * @see #getColor
  142. * @see #getColorSpace
  143. * @see #getColorComponents
  144. */
  145. private ColorSpace cs = null;
  146. /*
  147. * JDK 1.1 serialVersionUID
  148. */
  149. private static final long serialVersionUID = 118526816881161077L;
  150. /**
  151. * Initialize JNI field and method IDs
  152. */
  153. private static native void initIDs();
  154. static {
  155. /** 4112352 - Calling getDefaultToolkit()
  156. ** here can cause this class to be accessed before it is fully
  157. ** initialized. DON'T DO IT!!!
  158. **
  159. ** Toolkit.getDefaultToolkit();
  160. **/
  161. /* ensure that the necessary native libraries are loaded */
  162. Toolkit.loadLibraries();
  163. initIDs();
  164. }
  165. /**
  166. * Checks the color integer components supplied for validity.
  167. * Throws an {@link IllegalArgumentException} if the value is out of
  168. * range.
  169. * @param r the Red component
  170. * @param g the Green component
  171. * @param b the Blue component
  172. **/
  173. private static void testColorValueRange(int r, int g, int b, int a) {
  174. boolean rangeError = false;
  175. String badComponentString = "";
  176. if ( a < 0 || a > 255) {
  177. rangeError = true;
  178. badComponentString = badComponentString + " Alpha";
  179. }
  180. if ( r < 0 || r > 255) {
  181. rangeError = true;
  182. badComponentString = badComponentString + " Red";
  183. }
  184. if ( g < 0 || g > 255) {
  185. rangeError = true;
  186. badComponentString = badComponentString + " Green";
  187. }
  188. if ( b < 0 || b > 255) {
  189. rangeError = true;
  190. badComponentString = badComponentString + " Blue";
  191. }
  192. if ( rangeError == true ) {
  193. throw new IllegalArgumentException("Color parameter outside of expected range:"
  194. + badComponentString);
  195. }
  196. }
  197. /**
  198. * Checks the color <code>float</code> components supplied for
  199. * validity.
  200. * Throws an <code>IllegalArgumentException</code> if the value is out
  201. * of range.
  202. * @param r the Red component
  203. * @param g the Green component
  204. * @param b the Blue component
  205. **/
  206. private static void testColorValueRange(float r, float g, float b, float a) {
  207. boolean rangeError = false;
  208. String badComponentString = "";
  209. if ( a < 0.0 || a > 1.0) {
  210. rangeError = true;
  211. badComponentString = badComponentString + " Alpha";
  212. }
  213. if ( r < 0.0 || r > 1.0) {
  214. rangeError = true;
  215. badComponentString = badComponentString + " Red";
  216. }
  217. if ( g < 0.0 || g > 1.0) {
  218. rangeError = true;
  219. badComponentString = badComponentString + " Green";
  220. }
  221. if ( b < 0.0 || b > 1.0) {
  222. rangeError = true;
  223. badComponentString = badComponentString + " Blue";
  224. }
  225. if ( rangeError == true ) {
  226. throw new IllegalArgumentException("Color parameter outside of expected range:"
  227. + badComponentString);
  228. }
  229. }
  230. /**
  231. * Creates an opaque sRGB color with the specified red, green,
  232. * and blue values in the range (0 - 255).
  233. * The actual color used in rendering depends
  234. * on finding the best match given the color space
  235. * available for a given output device.
  236. * Alpha is defaulted to 255.
  237. * @param r the red component
  238. * @param g the green component
  239. * @param b the blue component
  240. * @see #getRed
  241. * @see #getGreen
  242. * @see #getBlue
  243. * @see #getRGB
  244. */
  245. public Color(int r, int g, int b) {
  246. this(r, g, b, 255);
  247. }
  248. /**
  249. * Creates an sRGB color with the specified red, green, blue, and alpha
  250. * values in the range (0 - 255).
  251. * @param r the red component
  252. * @param g the green component
  253. * @param b the blue component
  254. * @param a the alpha component
  255. * @see #getRed
  256. * @see #getGreen
  257. * @see #getBlue
  258. * @see #getAlpha
  259. * @see #getRGB
  260. */
  261. public Color(int r, int g, int b, int a) {
  262. value = ((a & 0xFF) << 24) |
  263. ((r & 0xFF) << 16) |
  264. ((g & 0xFF) << 8) |
  265. ((b & 0xFF) << 0);
  266. testColorValueRange(r,g,b,a);
  267. }
  268. /**
  269. * Creates an opaque sRGB color with the specified combined RGB value
  270. * consisting of the red component in bits 16-23, the green component
  271. * in bits 8-15, and the blue component in bits 0-7. The actual color
  272. * used in rendering depends on finding the best match given the
  273. * color space available for a particular output device. Alpha is
  274. * defaulted to 255.
  275. * @param rgb the combined RGB components
  276. * @see java.awt.image.ColorModel#getRGBdefault
  277. * @see #getRed
  278. * @see #getGreen
  279. * @see #getBlue
  280. * @see #getRGB
  281. */
  282. public Color(int rgb) {
  283. value = 0xff000000 | rgb;
  284. }
  285. /**
  286. * Creates an sRGB color with the specified combined RGBA value consisting
  287. * of the alpha component in bits 24-31, the red component in bits 16-23,
  288. * the green component in bits 8-15, and the blue component in bits 0-7.
  289. * If the <code>hasalpha</code> argument is <code>false</code>, alpha
  290. * is defaulted to 255.
  291. * @param rgba the combined RGBA components
  292. * @param hasalpha <code>true</code> if the alpha bits are valid;
  293. * <code>false</code> otherwise
  294. * @see java.awt.image.ColorModel#getRGBdefault
  295. * @see #getRed
  296. * @see #getGreen
  297. * @see #getBlue
  298. * @see #getAlpha
  299. * @see #getRGB
  300. */
  301. public Color(int rgba, boolean hasalpha) {
  302. if (hasalpha) {
  303. value = rgba;
  304. } else {
  305. value = 0xff000000 | rgba;
  306. }
  307. }
  308. /**
  309. * Creates an opaque sRGB color with the specified red, green, and blue
  310. * values in the range (0.0 - 1.0). Alpha is defaulted to 1.0. The
  311. * actual color used in rendering depends on finding the best
  312. * match given the color space available for a particular output
  313. * device.
  314. * @param r the red component
  315. * @param g the green component
  316. * @param b the blue component
  317. * @see #getRed
  318. * @see #getGreen
  319. * @see #getBlue
  320. * @see #getRGB
  321. */
  322. public Color(float r, float g, float b) {
  323. this( (int) (r*255+0.5), (int) (g*255+0.5), (int) (b*255+0.5));
  324. testColorValueRange(r,g,b,1.0f);
  325. frgbvalue = new float[3];
  326. frgbvalue[0] = r;
  327. frgbvalue[1] = g;
  328. frgbvalue[2] = b;
  329. falpha = 1.0f;
  330. fvalue = frgbvalue;
  331. }
  332. /**
  333. * Creates an sRGB color with the specified red, green, blue, and
  334. * alpha values in the range (0.0 - 1.0). The actual color
  335. * used in rendering depends on finding the best match given the
  336. * color space available for a particular output device.
  337. * @param r the red component
  338. * @param g the green component
  339. * @param b the blue component
  340. * @param a the alpha component
  341. * @see #getRed
  342. * @see #getGreen
  343. * @see #getBlue
  344. * @see #getAlpha
  345. * @see #getRGB
  346. */
  347. public Color(float r, float g, float b, float a) {
  348. this((int)(r*255+0.5), (int)(g*255+0.5), (int)(b*255+0.5), (int)(a*255+0.5));
  349. frgbvalue = new float[3];
  350. frgbvalue[0] = r;
  351. frgbvalue[1] = g;
  352. frgbvalue[2] = b;
  353. falpha = a;
  354. fvalue = frgbvalue;
  355. }
  356. /**
  357. * Creates a color in the specified <code>ColorSpace</code>
  358. * with the color components specified in the <code>float</code>
  359. * array and the specified alpha. The number of components is
  360. * determined by the type of the <code>ColorSpace</code>. For
  361. * example, RGB requires 3 components, but CMYK requires 4
  362. * components.
  363. * @param cspace the <code>ColorSpace</code> to be used to
  364. * interpret the components
  365. * @param components an arbitrary number of color components
  366. * that is compatible with the
  367. * @param alpha alpha value
  368. * @throws IllegalArgumentException if any of the values in the
  369. * <code>components</code> array or <code>alpha</code> is
  370. * outside of the range 0.0 to 1.0
  371. * @see #getComponents
  372. * @see #getColorComponents
  373. */
  374. public Color(ColorSpace cspace, float components[], float alpha) {
  375. boolean rangeError = false;
  376. String badComponentString = "";
  377. int n = cspace.getNumComponents();
  378. fvalue = new float[n];
  379. for (int i = 0; i < n; i++) {
  380. if (components[i] < 0.0 || components[i] > 1.0) {
  381. rangeError = true;
  382. badComponentString = badComponentString + "Component " + i
  383. + " ";
  384. } else {
  385. fvalue[i] = components[i];
  386. }
  387. }
  388. if (alpha < 0.0 || alpha > 1.0) {
  389. rangeError = true;
  390. badComponentString = badComponentString + "Alpha";
  391. } else {
  392. falpha = alpha;
  393. }
  394. if (rangeError) {
  395. throw new IllegalArgumentException(
  396. "Color parameter outside of expected range: " +
  397. badComponentString);
  398. }
  399. frgbvalue = cspace.toRGB(fvalue);
  400. cs = cspace;
  401. value = ((((int)(falpha*255)) & 0xFF) << 24) |
  402. ((((int)(frgbvalue[0]*255)) & 0xFF) << 16) |
  403. ((((int)(frgbvalue[1]*255)) & 0xFF) << 8) |
  404. ((((int)(frgbvalue[2]*255)) & 0xFF) << 0);
  405. }
  406. /**
  407. * Returns the red component in the range 0-255 in the default sRGB
  408. * space.
  409. * @return the red component.
  410. * @see #getRGB
  411. */
  412. public int getRed() {
  413. return (getRGB() >> 16) & 0xFF;
  414. }
  415. /**
  416. * Returns the green component in the range 0-255 in the default sRGB
  417. * space.
  418. * @return the green component.
  419. * @see #getRGB
  420. */
  421. public int getGreen() {
  422. return (getRGB() >> 8) & 0xFF;
  423. }
  424. /**
  425. * Returns the blue component in the range 0-255 in the default sRGB
  426. * space.
  427. * @return the blue component.
  428. * @see #getRGB
  429. */
  430. public int getBlue() {
  431. return (getRGB() >> 0) & 0xFF;
  432. }
  433. /**
  434. * Returns the alpha component in the range 0-255.
  435. * @return the alpha component.
  436. * @see #getRGB
  437. */
  438. public int getAlpha() {
  439. return (getRGB() >> 24) & 0xff;
  440. }
  441. /**
  442. * Returns the RGB value representing the color in the default sRGB
  443. * {@link ColorModel}.
  444. * (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are
  445. * blue).
  446. * @return the RGB value of the color in the default sRGB
  447. * <code>ColorModel</code>.
  448. * @see java.awt.image.ColorModel#getRGBdefault
  449. * @see #getRed
  450. * @see #getGreen
  451. * @see #getBlue
  452. * @since JDK1.0
  453. */
  454. public int getRGB() {
  455. return value;
  456. }
  457. private static final double FACTOR = 0.7;
  458. /**
  459. * Creates a new <code>Color</code> that is a brighter version of this
  460. * <code>Color</code>.
  461. * <p>
  462. * This method applies an arbitrary scale factor to each of the three RGB
  463. * components of this <code>Color</code> to create a brighter version
  464. * of this <code>Color</code>. Although <code>brighter</code> and
  465. * <code>darker</code> are inverse operations, the results of a
  466. * series of invocations of these two methods might be inconsistent
  467. * because of rounding errors.
  468. * @return a new <code>Color</code> object that is
  469. * a brighter version of this <code>Color</code>.
  470. * @see java.awt.Color#darker
  471. * @since JDK1.0
  472. */
  473. public Color brighter() {
  474. int r = getRed();
  475. int g = getGreen();
  476. int b = getBlue();
  477. /* From 2D group:
  478. * 1. black.brighter() should return grey
  479. * 2. applying brighter to blue will always return blue, brighter
  480. * 3. non pure color (non zero rgb) will eventually return white
  481. */
  482. int i = (int)(1.0/(1.0-FACTOR));
  483. if ( r == 0 && g == 0 && b == 0) {
  484. return new Color(i, i, i);
  485. }
  486. if ( r > 0 && r < i ) r = i;
  487. if ( g > 0 && g < i ) g = i;
  488. if ( b > 0 && b < i ) b = i;
  489. return new Color(Math.min((int)(rFACTOR), 255),
  490. Math.min((int)(gFACTOR), 255),
  491. Math.min((int)(bFACTOR), 255));
  492. }
  493. /**
  494. * Creates a new <code>Color</code> that is a darker version of this
  495. * <code>Color</code>.
  496. * <p>
  497. * This method applies an arbitrary scale factor to each of the three RGB
  498. * components of this <code>Color</code> to create a darker version of
  499. * this <code>Color</code>. Although <code>brighter</code> and
  500. * <code>darker</code> are inverse operations, the results of a series
  501. * of invocations of these two methods might be inconsistent because
  502. * of rounding errors.
  503. * @return a new <code>Color</code> object that is
  504. * a darker version of this <code>Color</code>.
  505. * @see java.awt.Color#brighter
  506. * @since JDK1.0
  507. */
  508. public Color darker() {
  509. return new Color(Math.max((int)(getRed() *FACTOR), 0),
  510. Math.max((int)(getGreen()*FACTOR), 0),
  511. Math.max((int)(getBlue() *FACTOR), 0));
  512. }
  513. /**
  514. * Computes the hash code for this <code>Color</code>.
  515. * @return a hash code value for this object.
  516. * @since JDK1.0
  517. */
  518. public int hashCode() {
  519. return value;
  520. }
  521. /**
  522. * Determines whether another object is equal to this
  523. * <code>Color</code>.
  524. * <p>
  525. * The result is <code>true</code> if and only if the argument is not
  526. * <code>null</code> and is a <code>Color</code> object that has the same
  527. * red, green, and blue values as this object.
  528. * @param obj the object to test for equality with this
  529. * <code>Color</code>
  530. * @return <code>true</code> if the objects are the same;
  531. * <code>false</code> otherwise.
  532. * @since JDK1.0
  533. */
  534. public boolean equals(Object obj) {
  535. return obj instanceof Color && ((Color)obj).value == this.value;
  536. }
  537. /**
  538. * Returns a string representation of this <code>Color</code>. This
  539. * method is intended to be used only for debugging purposes. The
  540. * content and format of the returned string might vary between
  541. * implementations. The returned string might be empty but cannot
  542. * be <code>null</code>.
  543. *
  544. * @return a string representation of this <code>Color</code>.
  545. */
  546. public String toString() {
  547. return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]";
  548. }
  549. /**
  550. * Converts a <code>String</code> to an integer and returns the
  551. * specified opaque <code>Color</code>. This method handles string
  552. * formats that are used to represent octal and hexidecimal numbers.
  553. * @param nm a <code>String</code> that represents
  554. * an opaque color as a 24-bit integer
  555. * @return the new <code>Color</code> object.
  556. * @see java.lang.Integer#decode
  557. * @exception NumberFormatException if the specified string cannot
  558. * be interpreted as a decimal,
  559. * octal, or hexidecimal integer.
  560. * @since JDK1.1
  561. */
  562. public static Color decode(String nm) throws NumberFormatException {
  563. Integer intval = Integer.decode(nm);
  564. int i = intval.intValue();
  565. return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  566. }
  567. /**
  568. * Finds a color in the system properties.
  569. * <p>
  570. * The argument is treated as the name of a system property to
  571. * be obtained. The string value of this property is then interpreted
  572. * as an integer which is then converted to a <code>Color</code>
  573. * object.
  574. * <p>
  575. * If the specified property is not found or could not be parsed as
  576. * an integer then <code>null</code> is returned.
  577. * @param nm the name of the color property
  578. * @return the <code>Color</code> converted from the system
  579. * property.
  580. * @see java.lang.System#getProperty(java.lang.String)
  581. * @see java.lang.Integer#getInteger(java.lang.String)
  582. * @see java.awt.Color#Color(int)
  583. * @since JDK1.0
  584. */
  585. public static Color getColor(String nm) {
  586. return getColor(nm, null);
  587. }
  588. /**
  589. * Finds a color in the system properties.
  590. * <p>
  591. * The first argument is treated as the name of a system property to
  592. * be obtained. The string value of this property is then interpreted
  593. * as an integer which is then converted to a <code>Color</code>
  594. * object.
  595. * <p>
  596. * If the specified property is not found or cannot be parsed as
  597. * an integer then the <code>Color</code> specified by the second
  598. * argument is returned instead.
  599. * @param nm the name of the color property
  600. * @param v the default <code>Color</code>
  601. * @return the <code>Color</code> converted from the system
  602. * property, or the specified <code>Color</code>.
  603. * @see java.lang.System#getProperty(java.lang.String)
  604. * @see java.lang.Integer#getInteger(java.lang.String)
  605. * @see java.awt.Color#Color(int)
  606. * @since JDK1.0
  607. */
  608. public static Color getColor(String nm, Color v) {
  609. Integer intval = Integer.getInteger(nm);
  610. if (intval == null) {
  611. return v;
  612. }
  613. int i = intval.intValue();
  614. return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  615. }
  616. /**
  617. * Finds a color in the system properties.
  618. * <p>
  619. * The first argument is treated as the name of a system property to
  620. * be obtained. The string value of this property is then interpreted
  621. * as an integer which is then converted to a <code>Color</code>
  622. * object.
  623. * <p>
  624. * If the specified property is not found or could not be parsed as
  625. * an integer then the integer value <code>v</code> is used instead,
  626. * and is converted to a <code>Color</code> object.
  627. * @param nm the name of the color property
  628. * @param v the default color value, as an integer
  629. * @return the <code>Color</code> converted from the system
  630. * property or the <code>Color</code> converted from
  631. * the specified integer.
  632. * @see java.lang.System#getProperty(java.lang.String)
  633. * @see java.lang.Integer#getInteger(java.lang.String)
  634. * @see java.awt.Color#Color(int)
  635. * @since JDK1.0
  636. */
  637. public static Color getColor(String nm, int v) {
  638. Integer intval = Integer.getInteger(nm);
  639. int i = (intval != null) ? intval.intValue() : v;
  640. return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, (i >> 0) & 0xFF);
  641. }
  642. /**
  643. * Converts the components of a color, as specified by the HSB
  644. * model, to an equivalent set of values for the default RGB model.
  645. * <p>
  646. * The <code>saturation</code> and <code>brightness</code> components
  647. * should be floating-point values between zero and one
  648. * (numbers in the range 0.0-1.0). The <code>hue</code> component
  649. * can be any floating-point number. The floor of this number is
  650. * subtracted from it to create a fraction between 0 and 1. This
  651. * fractional number is then multiplied by 360 to produce the hue
  652. * angle in the HSB color model.
  653. * <p>
  654. * The integer that is returned by <code>HSBtoRGB</code> encodes the
  655. * value of a color in bits 0-23 of an integer value that is the same
  656. * format used by the method {@link #getRGB() <code>getRGB</code>}.
  657. * This integer can be supplied as an argument to the
  658. * <code>Color</code> constructor that takes a single integer argument.
  659. * @param hue the hue component of the color
  660. * @param saturation the saturation of the color
  661. * @param brightness the brightness of the color
  662. * @return the RGB value of the color with the indicated hue,
  663. * saturation, and brightness.
  664. * @see java.awt.Color#getRGB()
  665. * @see java.awt.Color#Color(int)
  666. * @see java.awt.image.ColorModel#getRGBdefault()
  667. * @since JDK1.0
  668. */
  669. public static int HSBtoRGB(float hue, float saturation, float brightness) {
  670. int r = 0, g = 0, b = 0;
  671. if (saturation == 0) {
  672. r = g = b = (int) (brightness * 255.0f + 0.5f);
  673. } else {
  674. float h = (hue - (float)Math.floor(hue)) * 6.0f;
  675. float f = h - (float)java.lang.Math.floor(h);
  676. float p = brightness * (1.0f - saturation);
  677. float q = brightness * (1.0f - saturation * f);
  678. float t = brightness * (1.0f - (saturation * (1.0f - f)));
  679. switch ((int) h) {
  680. case 0:
  681. r = (int) (brightness * 255.0f + 0.5f);
  682. g = (int) (t * 255.0f + 0.5f);
  683. b = (int) (p * 255.0f + 0.5f);
  684. break;
  685. case 1:
  686. r = (int) (q * 255.0f + 0.5f);
  687. g = (int) (brightness * 255.0f + 0.5f);
  688. b = (int) (p * 255.0f + 0.5f);
  689. break;
  690. case 2:
  691. r = (int) (p * 255.0f + 0.5f);
  692. g = (int) (brightness * 255.0f + 0.5f);
  693. b = (int) (t * 255.0f + 0.5f);
  694. break;
  695. case 3:
  696. r = (int) (p * 255.0f + 0.5f);
  697. g = (int) (q * 255.0f + 0.5f);
  698. b = (int) (brightness * 255.0f + 0.5f);
  699. break;
  700. case 4:
  701. r = (int) (t * 255.0f + 0.5f);
  702. g = (int) (p * 255.0f + 0.5f);
  703. b = (int) (brightness * 255.0f + 0.5f);
  704. break;
  705. case 5:
  706. r = (int) (brightness * 255.0f + 0.5f);
  707. g = (int) (p * 255.0f + 0.5f);
  708. b = (int) (q * 255.0f + 0.5f);
  709. break;
  710. }
  711. }
  712. return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
  713. }
  714. /**
  715. * Converts the components of a color, as specified by the default RGB
  716. * model, to an equivalent set of values for hue, saturation, and
  717. * brightness that are the three components of the HSB model.
  718. * <p>
  719. * If the <code>hsbvals</code> argument is <code>null</code>, then a
  720. * new array is allocated to return the result. Otherwise, the method
  721. * returns the array <code>hsbvals</code>, with the values put into
  722. * that array.
  723. * @param r the red component of the color
  724. * @param g the green component of the color
  725. * @param b the blue component of the color
  726. * @param hsbvals the array used to return the
  727. * three HSB values, or <code>null</code>
  728. * @return an array of three elements containing the hue, saturation,
  729. * and brightness (in that order), of the color with
  730. * the indicated red, green, and blue components.
  731. * @see java.awt.Color#getRGB()
  732. * @see java.awt.Color#Color(int)
  733. * @see java.awt.image.ColorModel#getRGBdefault()
  734. * @since JDK1.0
  735. */
  736. public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
  737. float hue, saturation, brightness;
  738. if (hsbvals == null) {
  739. hsbvals = new float[3];
  740. }
  741. int cmax = (r > g) ? r : g;
  742. if (b > cmax) cmax = b;
  743. int cmin = (r < g) ? r : g;
  744. if (b < cmin) cmin = b;
  745. brightness = ((float) cmax) / 255.0f;
  746. if (cmax != 0)
  747. saturation = ((float) (cmax - cmin)) / ((float) cmax);
  748. else
  749. saturation = 0;
  750. if (saturation == 0)
  751. hue = 0;
  752. else {
  753. float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
  754. float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
  755. float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
  756. if (r == cmax)
  757. hue = bluec - greenc;
  758. else if (g == cmax)
  759. hue = 2.0f + redc - bluec;
  760. else
  761. hue = 4.0f + greenc - redc;
  762. hue = hue / 6.0f;
  763. if (hue < 0)
  764. hue = hue + 1.0f;
  765. }
  766. hsbvals[0] = hue;
  767. hsbvals[1] = saturation;
  768. hsbvals[2] = brightness;
  769. return hsbvals;
  770. }
  771. /**
  772. * Creates a <code>Color</code> object based on the specified values
  773. * for the HSB color model.
  774. * <p>
  775. * The <code>s</code> and <code>b</code> components should be
  776. * floating-point values between zero and one
  777. * (numbers in the range 0.0-1.0). The <code>h</code> component
  778. * can be any floating-point number. The floor of this number is
  779. * subtracted from it to create a fraction between 0 and 1. This
  780. * fractional number is then multiplied by 360 to produce the hue
  781. * angle in the HSB color model.
  782. * @param h the hue component
  783. * @param s the saturation of the color
  784. * @param b the brightness of the color
  785. * @return a <code>Color</code> object with the specified hue,
  786. * saturation, and brightness.
  787. * @since JDK1.0
  788. */
  789. public static Color getHSBColor(float h, float s, float b) {
  790. return new Color(HSBtoRGB(h, s, b));
  791. }
  792. /**
  793. * Returns a <code>float</code> array containing the color and alpha
  794. * components of the <code>Color</code>, as represented in the default
  795. * sRGB color space.
  796. * If <code>compArray</code> is <code>null</code>, an array of length
  797. * 4 is created for the return value. Otherwise,
  798. * <code>compArray</code> must have length 4 or greater,
  799. * and it is filled in with the components and returned.
  800. * @param compArray an array that this method fills with
  801. * color and alpha components and returns
  802. * @return the RGBA components in a <code>float</code> array.
  803. */
  804. public float[] getRGBComponents(float[] compArray) {
  805. float[] f;
  806. if (compArray == null) {
  807. f = new float[4];
  808. } else {
  809. f = compArray;
  810. }
  811. if (frgbvalue == null) {
  812. f[0] = ((float)getRed())/255f;
  813. f[1] = ((float)getGreen())/255f;
  814. f[2] = ((float)getBlue())/255f;
  815. f[3] = ((float)getAlpha())/255f;
  816. } else {
  817. f[0] = frgbvalue[0];
  818. f[1] = frgbvalue[1];
  819. f[2] = frgbvalue[2];
  820. f[3] = falpha;
  821. }
  822. return f;
  823. }
  824. /**
  825. * Returns a <code>float</code> array containing only the color
  826. * components of the <code>Color</code>, in the default sRGB color
  827. * space. If <code>compArray</code> is <code>null</code>, an array of
  828. * length 3 is created for the return value. Otherwise,
  829. * <code>compArray</code> must have length 3 or greater, and it is
  830. * filled in with the components and returned.
  831. * @param compArray an array that this method fills with color
  832. * components and returns
  833. * @return the RGB components in a <code>float</code> array.
  834. */
  835. public float[] getRGBColorComponents(float[] compArray) {
  836. float[] f;
  837. if (compArray == null) {
  838. f = new float[3];
  839. } else {
  840. f = compArray;
  841. }
  842. if (frgbvalue == null) {
  843. f[0] = ((float)getRed())/255f;
  844. f[1] = ((float)getGreen())/255f;
  845. f[2] = ((float)getBlue())/255f;
  846. } else {
  847. f[0] = frgbvalue[0];
  848. f[1] = frgbvalue[1];
  849. f[2] = frgbvalue[2];
  850. }
  851. return f;
  852. }
  853. /**
  854. * Returns a <code>float</code> array containing the color and alpha
  855. * components of the <code>Color</code>, in the
  856. * <code>ColorSpace</code> of the <code>Color</code>.
  857. * If <code>compArray</code> is <code>null</code>, an array with
  858. * length equal to the number of components in the associated
  859. * <code>ColorSpace</code> plus one is created for
  860. * the return value. Otherwise, <code>compArray</code> must have at
  861. * least this length and it is filled in with the components and
  862. * returned.
  863. * @param compArray an array that this method fills with the color and
  864. * alpha components of this <code>Color</code> in its
  865. * <code>ColorSpace</code> and returns
  866. * @return the color and alpha components in a <code>float</code>
  867. * array.
  868. */
  869. public float[] getComponents(float[] compArray) {
  870. if (fvalue == null)
  871. return getRGBComponents(compArray);
  872. float[] f;
  873. int n = fvalue.length;
  874. if (compArray == null) {
  875. f = new float[n + 1];
  876. } else {
  877. f = compArray;
  878. }
  879. for (int i = 0; i < n; i++) {
  880. f[i] = fvalue[i];
  881. }
  882. f[n] = falpha;
  883. return f;
  884. }
  885. /**
  886. * Returns a <code>float</code> array containing only the color
  887. * components of the <code>Color</code>, in the
  888. * <code>ColorSpace</code> of the <code>Color</code>.
  889. * If <code>compArray</code> is <code>null</code>, an array with
  890. * length equal to the number of components in the associated
  891. * <code>ColorSpace</code> is created for
  892. * the return value. Otherwise, <code>compArray</code> must have at
  893. * least this length and it is filled in with the components and
  894. * returned.
  895. * @param compArray an array that this method fills with the color
  896. * components of this <code>Color</code> in its
  897. * <code>ColorSpace</code> and returns
  898. * @return the color components in a <code>float</code> array.
  899. */
  900. public float[] getColorComponents(float[] compArray) {
  901. if (fvalue == null)
  902. return getRGBColorComponents(compArray);
  903. float[] f;
  904. int n = fvalue.length;
  905. if (compArray == null) {
  906. f = new float[n];
  907. } else {
  908. f = compArray;
  909. }
  910. for (int i = 0; i < n; i++) {
  911. f[i] = fvalue[i];
  912. }
  913. return f;
  914. }
  915. /**
  916. * Returns a <code>float</code> array containing the color and alpha
  917. * components of the <code>Color</code>, in the
  918. * <code>ColorSpace</code> specified by the <code>cspace</code>
  919. * parameter. If <code>compArray</code> is <code>null</code>, an
  920. * array with length equal to the number of components in
  921. * <code>cspace</code> plus one is created for the return value.
  922. * Otherwise, <code>compArray</code> must have at least this
  923. * length, and it is filled in with the components and returned.
  924. * @param cspace a specified <code>ColorSpace</code>
  925. * @param compArray an array that this method fills with the
  926. * color and alpha components of this <code>Color</code> in
  927. * the specified <code>ColorSpace</code> and returns
  928. * @return the color and alpha components in a <code>float</code>
  929. * array.
  930. */
  931. public float[] getComponents(ColorSpace cspace, float[] compArray) {
  932. if (cs == null) {
  933. cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  934. }
  935. float f[];
  936. if (fvalue == null) {
  937. f = new float[3];
  938. f[0] = ((float)getRed())/255f;
  939. f[1] = ((float)getGreen())/255f;
  940. f[2] = ((float)getBlue())/255f;
  941. } else {
  942. f = fvalue;
  943. }
  944. float tmp[] = cs.toCIEXYZ(f);
  945. float tmpout[] = cspace.fromCIEXYZ(tmp);
  946. if (compArray == null) {
  947. compArray = new float[tmpout.length + 1];
  948. }
  949. for (int i = 0 ; i < tmpout.length ; i++) {
  950. compArray[i] = tmpout[i];
  951. }
  952. if (fvalue == null) {
  953. compArray[tmpout.length] = ((float)getAlpha())/255f;
  954. } else {
  955. compArray[tmpout.length] = falpha;
  956. }
  957. return compArray;
  958. }
  959. /**
  960. * Returns a <code>float</code> array containing only the color
  961. * components of the <code>Color</code> in the
  962. * <code>ColorSpace</code> specified by the <code>cspace</code>
  963. * parameter. If <code>compArray</code> is <code>null</code>, an array
  964. * with length equal to the number of components in
  965. * <code>cspace</code> is created for the return value. Otherwise,
  966. * <code>compArray</code> must have at least this length, and it is
  967. * filled in with the components and returned.
  968. * @param cspace a specified <code>ColorSpace</code>
  969. * @param compArray an array that this method fills with the color
  970. * components of this <code>Color</code> in the specified
  971. * <code>ColorSpace</code>
  972. * @return the color components in a <code>float</code> array.
  973. */
  974. public float[] getColorComponents(ColorSpace cspace, float[] compArray) {
  975. if (cs == null) {
  976. cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  977. }
  978. float f[];
  979. if (fvalue == null) {
  980. f = new float[3];
  981. f[0] = ((float)getRed())/255f;
  982. f[1] = ((float)getGreen())/255f;
  983. f[2] = ((float)getBlue())/255f;
  984. } else {
  985. f = fvalue;
  986. }
  987. float tmp[] = cs.toCIEXYZ(f);
  988. float tmpout[] = cspace.fromCIEXYZ(tmp);
  989. if (compArray == null) {
  990. return tmpout;
  991. }
  992. for (int i = 0 ; i < tmpout.length ; i++) {
  993. compArray[i] = tmpout[i];
  994. }
  995. return compArray;
  996. }
  997. /**
  998. * Returns the <code>ColorSpace</code> of this <code>Color</code>.
  999. * @return this <code>Color</code> object's <code>ColorSpace</code>.
  1000. */
  1001. public ColorSpace getColorSpace() {
  1002. if (cs == null) {
  1003. cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  1004. }
  1005. return cs;
  1006. }
  1007. // REMIND: this should really be a Ref!
  1008. /**
  1009. * The paint context used to generate a solid color pattern.
  1010. * @serial
  1011. * @see createContext()
  1012. */
  1013. private PaintContext theContext;
  1014. /**
  1015. * Creates and returns a {@link PaintContext} used to generate a solid
  1016. * color pattern. This enables a <code>Color</code> object to be used
  1017. * as an argument to any method requiring an object implementing the
  1018. * {@link Paint} interface.
  1019. * The same <code>PaintContext</code> is returned, regardless of
  1020. * whether or not <code>r</code>, <code>r2d</code>,
  1021. * <code>xform</code>, or <code>hints</code> are <code>null</code>.
  1022. * @param cm the specified <code>ColorModel</code>
  1023. * @param r the specified {@link Rectangle}
  1024. * @param r2d the specified {@link Rectangle2D}
  1025. * @param xform the specified {@link AffineTransform}
  1026. * @param hints the specified {@link RenderingHints}
  1027. * @return a <code>PaintContext</code> that is used to generate a
  1028. * solid color pattern.
  1029. * @see Paint
  1030. * @see PaintContext
  1031. * @see Graphics2D#setPaint
  1032. */
  1033. public synchronized PaintContext createContext(ColorModel cm, Rectangle r,
  1034. Rectangle2D r2d,
  1035. AffineTransform xform,
  1036. RenderingHints hints) {
  1037. PaintContext pc = theContext;
  1038. if (pc == null) {
  1039. pc = new ColorPaintContext(value, cm);
  1040. theContext = pc;
  1041. }
  1042. return pc;
  1043. }
  1044. /**
  1045. * Returns the transparency mode for this <code>Color</code>. This is
  1046. * required to implement the <code>Paint</code> interface.
  1047. * @return this <code>Color</code> object's transparency mode.
  1048. * @see Paint
  1049. * @see Transparency
  1050. * @see #createContext
  1051. */
  1052. public int getTransparency() {
  1053. int alpha = getAlpha();
  1054. if (alpha == 0xff) {
  1055. return Transparency.OPAQUE;
  1056. }
  1057. else if (alpha == 0) {
  1058. return Transparency.BITMASK;
  1059. }
  1060. else {
  1061. return Transparency.TRANSLUCENT;
  1062. }
  1063. }
  1064. }