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