1. /*
  2. * @(#)Color.java 1.72 03/01/23
  3. *
  4. * Copyright 2003 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 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. * @param r the red component
  289. * @param g the green component
  290. * @param b the blue component
  291. * @see #getRed
  292. * @see #getGreen
  293. * @see #getBlue
  294. * @see #getRGB
  295. */
  296. public Color(int r, int g, int b) {
  297. this(r, g, b, 255);
  298. }
  299. /**
  300. * Creates an sRGB color with the specified red, green, blue, and alpha
  301. * values in the range (0 - 255).
  302. * @param r the red component
  303. * @param g the green component
  304. * @param b the blue component
  305. * @param a the alpha component
  306. * @see #getRed
  307. * @see #getGreen
  308. * @see #getBlue
  309. * @see #getAlpha
  310. * @see #getRGB
  311. */
  312. public Color(int r, int g, int b, int a) {
  313. value = ((a & 0xFF) << 24) |
  314. ((r & 0xFF) << 16) |
  315. ((g & 0xFF) << 8) |
  316. ((b & 0xFF) << 0);
  317. testColorValueRange(r,g,b,a);
  318. }
  319. /**
  320. * Creates an opaque sRGB color with the specified combined RGB value
  321. * consisting of the red component in bits 16-23, the green component
  322. * in bits 8-15, and the blue component in bits 0-7. The actual color
  323. * used in rendering depends on finding the best match given the
  324. * color space available for a particular output device. Alpha is
  325. * defaulted to 255.
  326. * @param rgb the combined RGB components
  327. * @see java.awt.image.ColorModel#getRGBdefault
  328. * @see #getRed
  329. * @see #getGreen
  330. * @see #getBlue
  331. * @see #getRGB
  332. */
  333. public Color(int rgb) {
  334. value = 0xff000000 | rgb;
  335. }
  336. /**
  337. * Creates an sRGB color with the specified combined RGBA value consisting
  338. * of the alpha component in bits 24-31, the red component in bits 16-23,
  339. * the green component in bits 8-15, and the blue component in bits 0-7.
  340. * If the <code>hasalpha</code> argument is <code>false</code>, alpha
  341. * is defaulted to 255.
  342. * @param rgba the combined RGBA components
  343. * @param hasalpha <code>true</code> if the alpha bits are valid;
  344. * <code>false</code> otherwise
  345. * @see java.awt.image.ColorModel#getRGBdefault
  346. * @see #getRed
  347. * @see #getGreen
  348. * @see #getBlue
  349. * @see #getAlpha
  350. * @see #getRGB
  351. */
  352. public Color(int rgba, boolean hasalpha) {
  353. if (hasalpha) {
  354. value = rgba;
  355. } else {
  356. value = 0xff000000 | rgba;
  357. }
  358. }
  359. /**
  360. * Creates an opaque sRGB color with the specified red, green, and blue
  361. * values in the range (0.0 - 1.0). Alpha is defaulted to 1.0. The
  362. * actual color used in rendering depends on finding the best
  363. * match given the color space available for a particular output
  364. * device.
  365. * @param r the red component
  366. * @param g the green component
  367. * @param b the blue component
  368. * @see #getRed
  369. * @see #getGreen
  370. * @see #getBlue
  371. * @see #getRGB
  372. */
  373. public Color(float r, float g, float b) {
  374. this( (int) (r*255+0.5), (int) (g*255+0.5), (int) (b*255+0.5));
  375. testColorValueRange(r,g,b,1.0f);
  376. frgbvalue = new float[3];
  377. frgbvalue[0] = r;
  378. frgbvalue[1] = g;
  379. frgbvalue[2] = b;
  380. falpha = 1.0f;
  381. fvalue = frgbvalue;
  382. }
  383. /**
  384. * Creates an sRGB color with the specified red, green, blue, and
  385. * alpha values in the range (0.0 - 1.0). The actual color
  386. * used in rendering depends on finding the best match given the
  387. * color space available for a particular output device.
  388. * @param r the red component
  389. * @param g the green component
  390. * @param b the blue component
  391. * @param a the alpha component
  392. * @see #getRed
  393. * @see #getGreen
  394. * @see #getBlue
  395. * @see #getAlpha
  396. * @see #getRGB
  397. */
  398. public Color(float r, float g, float b, float a) {
  399. this((int)(r*255+0.5), (int)(g*255+0.5), (int)(b*255+0.5), (int)(a*255+0.5));
  400. frgbvalue = new float[3];
  401. frgbvalue[0] = r;
  402. frgbvalue[1] = g;
  403. frgbvalue[2] = b;
  404. falpha = a;
  405. fvalue = frgbvalue;
  406. }
  407. /**
  408. * Creates a color in the specified <code>ColorSpace</code>
  409. * with the color components specified in the <code>float</code>
  410. * array and the specified alpha. The number of components is
  411. * determined by the type of the <code>ColorSpace</code>. For
  412. * example, RGB requires 3 components, but CMYK requires 4
  413. * components.
  414. * @param cspace the <code>ColorSpace</code> to be used to
  415. * interpret the components
  416. * @param components an arbitrary number of color components
  417. * that is compatible with the
  418. * @param alpha alpha value
  419. * @throws IllegalArgumentException if any of the values in the
  420. * <code>components</code> array or <code>alpha</code> is
  421. * outside of the range 0.0 to 1.0
  422. * @see #getComponents
  423. * @see #getColorComponents
  424. */
  425. public Color(ColorSpace cspace, float components[], float alpha) {
  426. boolean rangeError = false;
  427. String badComponentString = "";
  428. int n = cspace.getNumComponents();
  429. fvalue = new float[n];
  430. for (int i = 0; i < n; i++) {
  431. if (components[i] < 0.0 || components[i] > 1.0) {
  432. rangeError = true;
  433. badComponentString = badComponentString + "Component " + i
  434. + " ";
  435. } else {
  436. fvalue[i] = components[i];
  437. }
  438. }
  439. if (alpha < 0.0 || alpha > 1.0) {
  440. rangeError = true;
  441. badComponentString = badComponentString + "Alpha";
  442. } else {
  443. falpha = alpha;
  444. }
  445. if (rangeError) {
  446. throw new IllegalArgumentException(
  447. "Color parameter outside of expected range: " +
  448. badComponentString);
  449. }
  450. frgbvalue = cspace.toRGB(fvalue);
  451. cs = cspace;
  452. value = ((((int)(falpha*255)) & 0xFF) << 24) |
  453. ((((int)(frgbvalue[0]*255)) & 0xFF) << 16) |
  454. ((((int)(frgbvalue[1]*255)) & 0xFF) << 8) |
  455. ((((int)(frgbvalue[2]*255)) & 0xFF) << 0);
  456. }
  457. /**
  458. * Returns the red component in the range 0-255 in the default sRGB
  459. * space.
  460. * @return the red component.
  461. * @see #getRGB
  462. */
  463. public int getRed() {
  464. return (getRGB() >> 16) & 0xFF;
  465. }
  466. /**
  467. * Returns the green component in the range 0-255 in the default sRGB
  468. * space.
  469. * @return the green component.
  470. * @see #getRGB
  471. */
  472. public int getGreen() {
  473. return (getRGB() >> 8) & 0xFF;
  474. }
  475. /**
  476. * Returns the blue component in the range 0-255 in the default sRGB
  477. * space.
  478. * @return the blue component.
  479. * @see #getRGB
  480. */
  481. public int getBlue() {
  482. return (getRGB() >> 0) & 0xFF;
  483. }
  484. /**
  485. * Returns the alpha component in the range 0-255.
  486. * @return the alpha component.
  487. * @see #getRGB
  488. */
  489. public int getAlpha() {
  490. return (getRGB() >> 24) & 0xff;
  491. }
  492. /**
  493. * Returns the RGB value representing the color in the default sRGB
  494. * {@link ColorModel}.
  495. * (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are
  496. * blue).
  497. * @return the RGB value of the color in the default sRGB
  498. * <code>ColorModel</code>.
  499. * @see java.awt.image.ColorModel#getRGBdefault
  500. * @see #getRed
  501. * @see #getGreen
  502. * @see #getBlue
  503. * @since JDK1.0
  504. */
  505. public int getRGB() {
  506. return value;
  507. }
  508. private static final double FACTOR = 0.7;
  509. /**
  510. * Creates a new <code>Color</code> that is a brighter version of this
  511. * <code>Color</code>.
  512. * <p>
  513. * This method applies an arbitrary scale factor to each of the three RGB
  514. * components of this <code>Color</code> to create a brighter version
  515. * of this <code>Color</code>. Although <code>brighter</code> and
  516. * <code>darker</code> are inverse operations, the results of a
  517. * series of invocations of these two methods might be inconsistent
  518. * because of rounding errors.
  519. * @return a new <code>Color</code> object that is
  520. * a brighter version of this <code>Color</code>.
  521. * @see java.awt.Color#darker
  522. * @since JDK1.0
  523. */
  524. public Color brighter() {
  525. int r = getRed();
  526. int g = getGreen();
  527. int b = getBlue();
  528. /* From 2D group:
  529. * 1. black.brighter() should return grey
  530. * 2. applying brighter to blue will always return blue, brighter
  531. * 3. non pure color (non zero rgb) will eventually return white
  532. */
  533. int i = (int)(1.0/(1.0-FACTOR));
  534. if ( r == 0 && g == 0 && b == 0) {
  535. return new Color(i, i, i);
  536. }
  537. if ( r > 0 && r < i ) r = i;
  538. if ( g > 0 && g < i ) g = i;
  539. if ( b > 0 && b < i ) b = i;
  540. return new Color(Math.min((int)(rFACTOR), 255),
  541. Math.min((int)(gFACTOR), 255),
  542. Math.min((int)(bFACTOR), 255));
  543. }
  544. /**
  545. * Creates a new <code>Color</code> that is a darker version of this
  546. * <code>Color</code>.
  547. * <p>
  548. * This method applies an arbitrary scale factor to each of the three RGB
  549. * components of this <code>Color</code> to create a darker version of
  550. * this <code>Color</code>. Although <code>brighter</code> and
  551. * <code>darker</code> are inverse operations, the results of a series
  552. * of invocations of these two methods might be inconsistent because
  553. * of rounding errors.
  554. * @return a new <code>Color</code> object that is
  555. * a darker version of this <code>Color</code>.
  556. * @see java.awt.Color#brighter
  557. * @since JDK1.0
  558. */
  559. public Color darker() {
  560. return new Color(Math.max((int)(getRed() *FACTOR), 0),
  561. Math.max((int)(getGreen()*FACTOR), 0),
  562. Math.max((int)(getBlue() *FACTOR), 0));
  563. }
  564. /**
  565. * Computes the hash code for this <code>Color</code>.
  566. * @return a hash code value for this object.
  567. * @since JDK1.0
  568. */
  569. public int hashCode() {
  570. return value;
  571. }
  572. /**
  573. * Determines whether another object is equal to this
  574. * <code>Color</code>.
  575. * <p>
  576. * The result is <code>true</code> if and only if the argument is not
  577. * <code>null</code> and is a <code>Color</code> object that has the same
  578. * red, green, blue, and alpha values as this object.
  579. * @param obj the object to test for equality with this
  580. * <code>Color</code>
  581. * @return <code>true</code> if the objects are the same;
  582. * <code>false</code> otherwise.
  583. * @since JDK1.0
  584. */
  585. public boolean equals(Object obj) {
  586. return obj instanceof Color && ((Color)obj).value == this.value;
  587. }
  588. /**
  589. * Returns a string representation of this <code>Color</code>. This
  590. * method is intended to be used only for debugging purposes. The
  591. * content and format of the returned string might vary between
  592. * implementations. The returned string might be empty but cannot
  593. * be <code>null</code>.
  594. *
  595. * @return a string representation of this <code>Color</code>.
  596. */
  597. public String toString() {
  598. return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]";
  599. }
  600. /**
  601. * Converts a <code>String</code> to an integer and returns the
  602. * specified opaque <code>Color</code>. This method handles string
  603. * formats that are used to represent octal and hexidecimal numbers.
  604. * @param nm a <code>String</code> that represents
  605. * an opaque color as a 24-bit integer
  606. * @return the new <code>Color</code> object.
  607. * @see java.lang.Integer#decode
  608. * @exception NumberFormatException if the specified string cannot
  609. * be interpreted as a decimal,
  610. * octal, or hexidecimal integer.
  611. * @since JDK1.1
  612. */
  613. public static Color decode(String nm) throws NumberFormatException {
  614. Integer intval = Integer.decode(nm);
  615. int i = intval.intValue();
  616. return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  617. }
  618. /**
  619. * Finds a color in the system properties.
  620. * <p>
  621. * The argument is treated as the name of a system property to
  622. * be obtained. The string value of this property is then interpreted
  623. * as an integer which is then converted to a <code>Color</code>
  624. * object.
  625. * <p>
  626. * If the specified property is not found or could not be parsed as
  627. * an integer then <code>null</code> is returned.
  628. * @param nm the name of the color property
  629. * @return the <code>Color</code> converted from the system
  630. * property.
  631. * @see java.lang.System#getProperty(java.lang.String)
  632. * @see java.lang.Integer#getInteger(java.lang.String)
  633. * @see java.awt.Color#Color(int)
  634. * @since JDK1.0
  635. */
  636. public static Color getColor(String nm) {
  637. return getColor(nm, null);
  638. }
  639. /**
  640. * Finds a color in the system properties.
  641. * <p>
  642. * The first argument is treated as the name of a system property to
  643. * be obtained. The string value of this property is then interpreted
  644. * as an integer which is then converted to a <code>Color</code>
  645. * object.
  646. * <p>
  647. * If the specified property is not found or cannot be parsed as
  648. * an integer then the <code>Color</code> specified by the second
  649. * argument is returned instead.
  650. * @param nm the name of the color property
  651. * @param v the default <code>Color</code>
  652. * @return the <code>Color</code> converted from the system
  653. * property, or the specified <code>Color</code>.
  654. * @see java.lang.System#getProperty(java.lang.String)
  655. * @see java.lang.Integer#getInteger(java.lang.String)
  656. * @see java.awt.Color#Color(int)
  657. * @since JDK1.0
  658. */
  659. public static Color getColor(String nm, Color v) {
  660. Integer intval = Integer.getInteger(nm);
  661. if (intval == null) {
  662. return v;
  663. }
  664. int i = intval.intValue();
  665. return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  666. }
  667. /**
  668. * Finds a color in the system properties.
  669. * <p>
  670. * The first argument is treated as the name of a system property to
  671. * be obtained. The string value of this property is then interpreted
  672. * as an integer which is then converted to a <code>Color</code>
  673. * object.
  674. * <p>
  675. * If the specified property is not found or could not be parsed as
  676. * an integer then the integer value <code>v</code> is used instead,
  677. * and is converted to a <code>Color</code> object.
  678. * @param nm the name of the color property
  679. * @param v the default color value, as an integer
  680. * @return the <code>Color</code> converted from the system
  681. * property or the <code>Color</code> converted from
  682. * the specified integer.
  683. * @see java.lang.System#getProperty(java.lang.String)
  684. * @see java.lang.Integer#getInteger(java.lang.String)
  685. * @see java.awt.Color#Color(int)
  686. * @since JDK1.0
  687. */
  688. public static Color getColor(String nm, int v) {
  689. Integer intval = Integer.getInteger(nm);
  690. int i = (intval != null) ? intval.intValue() : v;
  691. return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, (i >> 0) & 0xFF);
  692. }
  693. /**
  694. * Converts the components of a color, as specified by the HSB
  695. * model, to an equivalent set of values for the default RGB model.
  696. * <p>
  697. * The <code>saturation</code> and <code>brightness</code> components
  698. * should be floating-point values between zero and one
  699. * (numbers in the range 0.0-1.0). The <code>hue</code> component
  700. * can be any floating-point number. The floor of this number is
  701. * subtracted from it to create a fraction between 0 and 1. This
  702. * fractional number is then multiplied by 360 to produce the hue
  703. * angle in the HSB color model.
  704. * <p>
  705. * The integer that is returned by <code>HSBtoRGB</code> encodes the
  706. * value of a color in bits 0-23 of an integer value that is the same
  707. * format used by the method {@link #getRGB() <code>getRGB</code>}.
  708. * This integer can be supplied as an argument to the
  709. * <code>Color</code> constructor that takes a single integer argument.
  710. * @param hue the hue component of the color
  711. * @param saturation the saturation of the color
  712. * @param brightness the brightness of the color
  713. * @return the RGB value of the color with the indicated hue,
  714. * saturation, and brightness.
  715. * @see java.awt.Color#getRGB()
  716. * @see java.awt.Color#Color(int)
  717. * @see java.awt.image.ColorModel#getRGBdefault()
  718. * @since JDK1.0
  719. */
  720. public static int HSBtoRGB(float hue, float saturation, float brightness) {
  721. int r = 0, g = 0, b = 0;
  722. if (saturation == 0) {
  723. r = g = b = (int) (brightness * 255.0f + 0.5f);
  724. } else {
  725. float h = (hue - (float)Math.floor(hue)) * 6.0f;
  726. float f = h - (float)java.lang.Math.floor(h);
  727. float p = brightness * (1.0f - saturation);
  728. float q = brightness * (1.0f - saturation * f);
  729. float t = brightness * (1.0f - (saturation * (1.0f - f)));
  730. switch ((int) h) {
  731. case 0:
  732. r = (int) (brightness * 255.0f + 0.5f);
  733. g = (int) (t * 255.0f + 0.5f);
  734. b = (int) (p * 255.0f + 0.5f);
  735. break;
  736. case 1:
  737. r = (int) (q * 255.0f + 0.5f);
  738. g = (int) (brightness * 255.0f + 0.5f);
  739. b = (int) (p * 255.0f + 0.5f);
  740. break;
  741. case 2:
  742. r = (int) (p * 255.0f + 0.5f);
  743. g = (int) (brightness * 255.0f + 0.5f);
  744. b = (int) (t * 255.0f + 0.5f);
  745. break;
  746. case 3:
  747. r = (int) (p * 255.0f + 0.5f);
  748. g = (int) (q * 255.0f + 0.5f);
  749. b = (int) (brightness * 255.0f + 0.5f);
  750. break;
  751. case 4:
  752. r = (int) (t * 255.0f + 0.5f);
  753. g = (int) (p * 255.0f + 0.5f);
  754. b = (int) (brightness * 255.0f + 0.5f);
  755. break;
  756. case 5:
  757. r = (int) (brightness * 255.0f + 0.5f);
  758. g = (int) (p * 255.0f + 0.5f);
  759. b = (int) (q * 255.0f + 0.5f);
  760. break;
  761. }
  762. }
  763. return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
  764. }
  765. /**
  766. * Converts the components of a color, as specified by the default RGB
  767. * model, to an equivalent set of values for hue, saturation, and
  768. * brightness that are the three components of the HSB model.
  769. * <p>
  770. * If the <code>hsbvals</code> argument is <code>null</code>, then a
  771. * new array is allocated to return the result. Otherwise, the method
  772. * returns the array <code>hsbvals</code>, with the values put into
  773. * that array.
  774. * @param r the red component of the color
  775. * @param g the green component of the color
  776. * @param b the blue component of the color
  777. * @param hsbvals the array used to return the
  778. * three HSB values, or <code>null</code>
  779. * @return an array of three elements containing the hue, saturation,
  780. * and brightness (in that order), of the color with
  781. * the indicated red, green, and blue components.
  782. * @see java.awt.Color#getRGB()
  783. * @see java.awt.Color#Color(int)
  784. * @see java.awt.image.ColorModel#getRGBdefault()
  785. * @since JDK1.0
  786. */
  787. public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
  788. float hue, saturation, brightness;
  789. if (hsbvals == null) {
  790. hsbvals = new float[3];
  791. }
  792. int cmax = (r > g) ? r : g;
  793. if (b > cmax) cmax = b;
  794. int cmin = (r < g) ? r : g;
  795. if (b < cmin) cmin = b;
  796. brightness = ((float) cmax) / 255.0f;
  797. if (cmax != 0)
  798. saturation = ((float) (cmax - cmin)) / ((float) cmax);
  799. else
  800. saturation = 0;
  801. if (saturation == 0)
  802. hue = 0;
  803. else {
  804. float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
  805. float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
  806. float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
  807. if (r == cmax)
  808. hue = bluec - greenc;
  809. else if (g == cmax)
  810. hue = 2.0f + redc - bluec;
  811. else
  812. hue = 4.0f + greenc - redc;
  813. hue = hue / 6.0f;
  814. if (hue < 0)
  815. hue = hue + 1.0f;
  816. }
  817. hsbvals[0] = hue;
  818. hsbvals[1] = saturation;
  819. hsbvals[2] = brightness;
  820. return hsbvals;
  821. }
  822. /**
  823. * Creates a <code>Color</code> object based on the specified values
  824. * for the HSB color model.
  825. * <p>
  826. * The <code>s</code> and <code>b</code> components should be
  827. * floating-point values between zero and one
  828. * (numbers in the range 0.0-1.0). The <code>h</code> component
  829. * can be any floating-point number. The floor of this number is
  830. * subtracted from it to create a fraction between 0 and 1. This
  831. * fractional number is then multiplied by 360 to produce the hue
  832. * angle in the HSB color model.
  833. * @param h the hue component
  834. * @param s the saturation of the color
  835. * @param b the brightness of the color
  836. * @return a <code>Color</code> object with the specified hue,
  837. * saturation, and brightness.
  838. * @since JDK1.0
  839. */
  840. public static Color getHSBColor(float h, float s, float b) {
  841. return new Color(HSBtoRGB(h, s, b));
  842. }
  843. /**
  844. * Returns a <code>float</code> array containing the color and alpha
  845. * components of the <code>Color</code>, as represented in the default
  846. * sRGB color space.
  847. * If <code>compArray</code> is <code>null</code>, an array of length
  848. * 4 is created for the return value. Otherwise,
  849. * <code>compArray</code> must have length 4 or greater,
  850. * and it is filled in with the components and returned.
  851. * @param compArray an array that this method fills with
  852. * color and alpha components and returns
  853. * @return the RGBA components in a <code>float</code> array.
  854. */
  855. public float[] getRGBComponents(float[] compArray) {
  856. float[] f;
  857. if (compArray == null) {
  858. f = new float[4];
  859. } else {
  860. f = compArray;
  861. }
  862. if (frgbvalue == null) {
  863. f[0] = ((float)getRed())/255f;
  864. f[1] = ((float)getGreen())/255f;
  865. f[2] = ((float)getBlue())/255f;
  866. f[3] = ((float)getAlpha())/255f;
  867. } else {
  868. f[0] = frgbvalue[0];
  869. f[1] = frgbvalue[1];
  870. f[2] = frgbvalue[2];
  871. f[3] = falpha;
  872. }
  873. return f;
  874. }
  875. /**
  876. * Returns a <code>float</code> array containing only the color
  877. * components of the <code>Color</code>, in the default sRGB color
  878. * space. If <code>compArray</code> is <code>null</code>, an array of
  879. * length 3 is created for the return value. Otherwise,
  880. * <code>compArray</code> must have length 3 or greater, and it is
  881. * filled in with the components and returned.
  882. * @param compArray an array that this method fills with color
  883. * components and returns
  884. * @return the RGB components in a <code>float</code> array.
  885. */
  886. public float[] getRGBColorComponents(float[] compArray) {
  887. float[] f;
  888. if (compArray == null) {
  889. f = new float[3];
  890. } else {
  891. f = compArray;
  892. }
  893. if (frgbvalue == null) {
  894. f[0] = ((float)getRed())/255f;
  895. f[1] = ((float)getGreen())/255f;
  896. f[2] = ((float)getBlue())/255f;
  897. } else {
  898. f[0] = frgbvalue[0];
  899. f[1] = frgbvalue[1];
  900. f[2] = frgbvalue[2];
  901. }
  902. return f;
  903. }
  904. /**
  905. * Returns a <code>float</code> array containing the color and alpha
  906. * components of the <code>Color</code>, in the
  907. * <code>ColorSpace</code> of the <code>Color</code>.
  908. * If <code>compArray</code> is <code>null</code>, an array with
  909. * length equal to the number of components in the associated
  910. * <code>ColorSpace</code> plus one is created for
  911. * the return value. Otherwise, <code>compArray</code> must have at
  912. * least this length and it is filled in with the components and
  913. * returned.
  914. * @param compArray an array that this method fills with the color and
  915. * alpha components of this <code>Color</code> in its
  916. * <code>ColorSpace</code> and returns
  917. * @return the color and alpha components in a <code>float</code>
  918. * array.
  919. */
  920. public float[] getComponents(float[] compArray) {
  921. if (fvalue == null)
  922. return getRGBComponents(compArray);
  923. float[] f;
  924. int n = fvalue.length;
  925. if (compArray == null) {
  926. f = new float[n + 1];
  927. } else {
  928. f = compArray;
  929. }
  930. for (int i = 0; i < n; i++) {
  931. f[i] = fvalue[i];
  932. }
  933. f[n] = falpha;
  934. return f;
  935. }
  936. /**
  937. * Returns a <code>float</code> array containing only the color
  938. * components of the <code>Color</code>, in the
  939. * <code>ColorSpace</code> of the <code>Color</code>.
  940. * If <code>compArray</code> is <code>null</code>, an array with
  941. * length equal to the number of components in the associated
  942. * <code>ColorSpace</code> is created for
  943. * the return value. Otherwise, <code>compArray</code> must have at
  944. * least this length and it is filled in with the components and
  945. * returned.
  946. * @param compArray an array that this method fills with the color
  947. * components of this <code>Color</code> in its
  948. * <code>ColorSpace</code> and returns
  949. * @return the color components in a <code>float</code> array.
  950. */
  951. public float[] getColorComponents(float[] compArray) {
  952. if (fvalue == null)
  953. return getRGBColorComponents(compArray);
  954. float[] f;
  955. int n = fvalue.length;
  956. if (compArray == null) {
  957. f = new float[n];
  958. } else {
  959. f = compArray;
  960. }
  961. for (int i = 0; i < n; i++) {
  962. f[i] = fvalue[i];
  963. }
  964. return f;
  965. }
  966. /**
  967. * Returns a <code>float</code> array containing the color and alpha
  968. * components of the <code>Color</code>, in the
  969. * <code>ColorSpace</code> specified by the <code>cspace</code>
  970. * parameter. If <code>compArray</code> is <code>null</code>, an
  971. * array with length equal to the number of components in
  972. * <code>cspace</code> plus one is created for the return value.
  973. * Otherwise, <code>compArray</code> must have at least this
  974. * length, and it is filled in with the components and returned.
  975. * @param cspace a specified <code>ColorSpace</code>
  976. * @param compArray an array that this method fills with the
  977. * color and alpha components of this <code>Color</code> in
  978. * the specified <code>ColorSpace</code> and returns
  979. * @return the color and alpha components in a <code>float</code>
  980. * array.
  981. */
  982. public float[] getComponents(ColorSpace cspace, float[] compArray) {
  983. if (cs == null) {
  984. cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  985. }
  986. float f[];
  987. if (fvalue == null) {
  988. f = new float[3];
  989. f[0] = ((float)getRed())/255f;
  990. f[1] = ((float)getGreen())/255f;
  991. f[2] = ((float)getBlue())/255f;
  992. } else {
  993. f = fvalue;
  994. }
  995. float tmp[] = cs.toCIEXYZ(f);
  996. float tmpout[] = cspace.fromCIEXYZ(tmp);
  997. if (compArray == null) {
  998. compArray = new float[tmpout.length + 1];
  999. }
  1000. for (int i = 0 ; i < tmpout.length ; i++) {
  1001. compArray[i] = tmpout[i];
  1002. }
  1003. if (fvalue == null) {
  1004. compArray[tmpout.length] = ((float)getAlpha())/255f;
  1005. } else {
  1006. compArray[tmpout.length] = falpha;
  1007. }
  1008. return compArray;
  1009. }
  1010. /**
  1011. * Returns a <code>float</code> array containing only the color
  1012. * components of the <code>Color</code> in the
  1013. * <code>ColorSpace</code> specified by the <code>cspace</code>
  1014. * parameter. If <code>compArray</code> is <code>null</code>, an array
  1015. * with length equal to the number of components in
  1016. * <code>cspace</code> is created for the return value. Otherwise,
  1017. * <code>compArray</code> must have at least this length, and it is
  1018. * filled in with the components and returned.
  1019. * @param cspace a specified <code>ColorSpace</code>
  1020. * @param compArray an array that this method fills with the color
  1021. * components of this <code>Color</code> in the specified
  1022. * <code>ColorSpace</code>
  1023. * @return the color components in a <code>float</code> array.
  1024. */
  1025. public float[] getColorComponents(ColorSpace cspace, float[] compArray) {
  1026. if (cs == null) {
  1027. cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  1028. }
  1029. float f[];
  1030. if (fvalue == null) {
  1031. f = new float[3];
  1032. f[0] = ((float)getRed())/255f;
  1033. f[1] = ((float)getGreen())/255f;
  1034. f[2] = ((float)getBlue())/255f;
  1035. } else {
  1036. f = fvalue;
  1037. }
  1038. float tmp[] = cs.toCIEXYZ(f);
  1039. float tmpout[] = cspace.fromCIEXYZ(tmp);
  1040. if (compArray == null) {
  1041. return tmpout;
  1042. }
  1043. for (int i = 0 ; i < tmpout.length ; i++) {
  1044. compArray[i] = tmpout[i];
  1045. }
  1046. return compArray;
  1047. }
  1048. /**
  1049. * Returns the <code>ColorSpace</code> of this <code>Color</code>.
  1050. * @return this <code>Color</code> object's <code>ColorSpace</code>.
  1051. */
  1052. public ColorSpace getColorSpace() {
  1053. if (cs == null) {
  1054. cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  1055. }
  1056. return cs;
  1057. }
  1058. // REMIND: this should really be a Ref!
  1059. /**
  1060. * The paint context used to generate a solid color pattern.
  1061. * @see createContext()
  1062. */
  1063. transient private PaintContext theContext;
  1064. /**
  1065. * Creates and returns a {@link PaintContext} used to generate a solid
  1066. * color pattern. This enables a <code>Color</code> object to be used
  1067. * as an argument to any method requiring an object implementing the
  1068. * {@link Paint} interface.
  1069. * The same <code>PaintContext</code> is returned, regardless of
  1070. * whether or not <code>r</code>, <code>r2d</code>,
  1071. * <code>xform</code>, or <code>hints</code> are <code>null</code>.
  1072. * @param cm the specified <code>ColorModel</code>
  1073. * @param r the specified {@link Rectangle}
  1074. * @param r2d the specified {@link Rectangle2D}
  1075. * @param xform the specified {@link AffineTransform}
  1076. * @param hints the specified {@link RenderingHints}
  1077. * @return a <code>PaintContext</code> that is used to generate a
  1078. * solid color pattern.
  1079. * @see Paint
  1080. * @see PaintContext
  1081. * @see Graphics2D#setPaint
  1082. */
  1083. public synchronized PaintContext createContext(ColorModel cm, Rectangle r,
  1084. Rectangle2D r2d,
  1085. AffineTransform xform,
  1086. RenderingHints hints) {
  1087. PaintContext pc = theContext;
  1088. if (pc == null) {
  1089. pc = new ColorPaintContext(value, cm);
  1090. theContext = pc;
  1091. }
  1092. return pc;
  1093. }
  1094. /**
  1095. * Returns the transparency mode for this <code>Color</code>. This is
  1096. * required to implement the <code>Paint</code> interface.
  1097. * @return this <code>Color</code> object's transparency mode.
  1098. * @see Paint
  1099. * @see Transparency
  1100. * @see #createContext
  1101. */
  1102. public int getTransparency() {
  1103. int alpha = getAlpha();
  1104. if (alpha == 0xff) {
  1105. return Transparency.OPAQUE;
  1106. }
  1107. else if (alpha == 0) {
  1108. return Transparency.BITMASK;
  1109. }
  1110. else {
  1111. return Transparency.TRANSLUCENT;
  1112. }
  1113. }
  1114. }