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