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