1 /*
2 * Copyright 1995-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.awt;
27
28 import java.beans.ConstructorProperties;
29 import java.awt.image.ColorModel;
30 import java.awt.geom.AffineTransform;
31 import java.awt.geom.Rectangle2D;
32 import java.awt.color.ColorSpace;
33
34 /**
35 * The <code>Color</code> 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</code> with an explicit alpha or
45 * getting the color/alpha components of a <code>Color</code>, 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 * <p>
54 * @version 10 Feb 1997
55 * @author Sami Shaio
56 * @author Arthur van Hoff
57 * @see ColorSpace
58 * @see AlphaComposite
59 */
60 public class Color implements Paint, java.io.Serializable {
61
62 /**
63 * The color white. In the default sRGB space.
64 */
65 public final static 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 final static Color WHITE = white;
72
73 /**
74 * The color light gray. In the default sRGB space.
75 */
76 public final static 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 final static Color LIGHT_GRAY = lightGray;
83
84 /**
85 * The color gray. In the default sRGB space.
86 */
87 public final static 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 final static Color GRAY = gray;
94
95 /**
96 * The color dark gray. In the default sRGB space.
97 */
98 public final static 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 final static Color DARK_GRAY = darkGray;
105
106 /**
107 * The color black. In the default sRGB space.
108 */
109 public final static 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 final static Color BLACK = black;
116
117 /**
118 * The color red. In the default sRGB space.
119 */
120 public final static 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 final static Color RED = red;
127
128 /**
129 * The color pink. In the default sRGB space.
130 */
131 public final static 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 final static Color PINK = pink;
138
139 /**
140 * The color orange. In the default sRGB space.
141 */
142 public final static 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 final static Color ORANGE = orange;
149
150 /**
151 * The color yellow. In the default sRGB space.
152 */
153 public final static 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 final static Color YELLOW = yellow;
160
161 /**
162 * The color green. In the default sRGB space.
163 */
164 public final static 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 final static Color GREEN = green;
171
172 /**
173 * The color magenta. In the default sRGB space.
174 */
175 public final static 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 final static Color MAGENTA = magenta;
182
183 /**
184 * The color cyan. In the default sRGB space.
185 */
186 public final static 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 final static Color CYAN = cyan;
193
194 /**
195 * The color blue. In the default sRGB space.
196 */
197 public final static 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 final static 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</code> as
214 * <code>float</code> components (no alpha).
215 * If <code>null</code> after object construction, this must be an
216 * sRGB color constructed with 8-bit precision, so compute from the
217 * <code>int</code> 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</code> as
226 * <code>float</code> components (no alpha).
227 * If <code>null</code> after object construction, this must be an
228 * sRGB color constructed with 8-bit precision, so compute from the
229 * <code>int</code> 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</code> component.
238 * If <code>frgbvalue</code> is <code>null</code>, this is not valid
239 * data, so compute from the <code>int</code> color value.
240 * @serial
241 * @see #getRGBComponents
242 * @see #getComponents
243 */
244 private float falpha = 0.0f;
245
246 /**
247 * The <code>ColorSpace</code>. If <code>null</code>, 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</code> components supplied for
317 * validity.
318 * Throws an <code>IllegalArgumentException</code> 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>, <code>g</code>
358 * or <code>b</code> 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>, <code>g</code>,
377 * <code>b</code> or <code>a</code> 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</code> argument is <code>false</code>, alpha
422 * is defaulted to 255.
423 *
424 * @param rgba the combined RGBA components
425 * @param hasalpha <code>true</code> if the alpha bits are valid;
426 * <code>false</code> 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>, <code>g</code>
450 * or <code>b</code> 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>, <code>g</code>
477 * <code>b</code> or <code>a</code> 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</code>
501 * with the color components specified in the <code>float</code>
502 * array and the specified alpha. The number of components is
503 * determined by the type of the <code>ColorSpace</code>. For
504 * example, RGB requires 3 components, but CMYK requires 4
505 * components.
506 * @param cspace the <code>ColorSpace</code> 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</code>
510 * @param alpha alpha value
511 * @throws IllegalArgumentException if any of the values in the
512 * <code>components</code> array or <code>alpha</code> 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</code>.
596 * @see java.awt.image.ColorModel#getRGBdefault
597 * @see #getRed
598 * @see #getGreen
599 * @see #getBlue
600 * @since JDK1.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</code> that is a brighter version of this
610 * <code>Color</code>.
611 * <p>
612 * This method applies an arbitrary scale factor to each of the three RGB
613 * components of this <code>Color</code> to create a brighter version
614 * of this <code>Color</code>. Although <code>brighter</code> and
615 * <code>darker</code> are inverse operations, the results of a
616 * series of invocations of these two methods might be inconsistent
617 * because of rounding errors.
618 * @return a new <code>Color</code> object that is
619 * a brighter version of this <code>Color</code>.
620 * @see java.awt.Color#darker
621 * @since JDK1.0
622 */
623 public Color brighter() {
624 int r = getRed();
625 int g = getGreen();
626 int b = getBlue();
627
628 /* From 2D group:
629 * 1. black.brighter() should return grey
630 * 2. applying brighter to blue will always return blue, brighter
631 * 3. non pure color (non zero rgb) will eventually return white
632 */
633 int i = (int)(1.0/(1.0-FACTOR));
634 if ( r == 0 && g == 0 && b == 0) {
635 return new Color(i, i, i);
636 }
637 if ( r > 0 && r < i ) r = i;
638 if ( g > 0 && g < i ) g = i;
639 if ( b > 0 && b < i ) b = i;
640
641 return new Color(Math.min((int)(r/FACTOR), 255),
642 Math.min((int)(g/FACTOR), 255),
643 Math.min((int)(b/FACTOR), 255));
644 }
645
646 /**
647 * Creates a new <code>Color</code> that is a darker version of this
648 * <code>Color</code>.
649 * <p>
650 * This method applies an arbitrary scale factor to each of the three RGB
651 * components of this <code>Color</code> to create a darker version of
652 * this <code>Color</code>. Although <code>brighter</code> and
653 * <code>darker</code> are inverse operations, the results of a series
654 * of invocations of these two methods might be inconsistent because
655 * of rounding errors.
656 * @return a new <code>Color</code> object that is
657 * a darker version of this <code>Color</code>.
658 * @see java.awt.Color#brighter
659 * @since JDK1.0
660 */
661 public Color darker() {
662 return new Color(Math.max((int)(getRed() *FACTOR), 0),
663 Math.max((int)(getGreen()*FACTOR), 0),
664 Math.max((int)(getBlue() *FACTOR), 0));
665 }
666
667 /**
668 * Computes the hash code for this <code>Color</code>.
669 * @return a hash code value for this object.
670 * @since JDK1.0
671 */
672 public int hashCode() {
673 return value;
674 }
675
676 /**
677 * Determines whether another object is equal to this
678 * <code>Color</code>.
679 * <p>
680 * The result is <code>true</code> if and only if the argument is not
681 * <code>null</code> and is a <code>Color</code> object that has the same
682 * red, green, blue, and alpha values as this object.
683 * @param obj the object to test for equality with this
684 * <code>Color</code>
685 * @return <code>true</code> if the objects are the same;
686 * <code>false</code> otherwise.
687 * @since JDK1.0
688 */
689 public boolean equals(Object obj) {
690 return obj instanceof Color && ((Color)obj).value == this.value;
691 }
692
693 /**
694 * Returns a string representation of this <code>Color</code>. This
695 * method is intended to be used only for debugging purposes. The
696 * content and format of the returned string might vary between
697 * implementations. The returned string might be empty but cannot
698 * be <code>null</code>.
699 *
700 * @return a string representation of this <code>Color</code>.
701 */
702 public String toString() {
703 return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]";
704 }
705
706 /**
707 * Converts a <code>String</code> to an integer and returns the
708 * specified opaque <code>Color</code>. This method handles string
709 * formats that are used to represent octal and hexadecimal numbers.
710 * @param nm a <code>String</code> that represents
711 * an opaque color as a 24-bit integer
712 * @return the new <code>Color</code> object.
713 * @see java.lang.Integer#decode
714 * @exception NumberFormatException if the specified string cannot
715 * be interpreted as a decimal,
716 * octal, or hexadecimal integer.
717 * @since JDK1.1
718 */
719 public static Color decode(String nm) throws NumberFormatException {
720 Integer intval = Integer.decode(nm);
721 int i = intval.intValue();
722 return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
723 }
724
725 /**
726 * Finds a color in the system properties.
727 * <p>
728 * The argument is treated as the name of a system property to
729 * be obtained. The string value of this property is then interpreted
730 * as an integer which is then converted to a <code>Color</code>
731 * object.
732 * <p>
733 * If the specified property is not found or could not be parsed as
734 * an integer then <code>null</code> is returned.
735 * @param nm the name of the color property
736 * @return the <code>Color</code> converted from the system
737 * property.
738 * @see java.lang.System#getProperty(java.lang.String)
739 * @see java.lang.Integer#getInteger(java.lang.String)
740 * @see java.awt.Color#Color(int)
741 * @since JDK1.0
742 */
743 public static Color getColor(String nm) {
744 return getColor(nm, null);
745 }
746
747 /**
748 * Finds a color in the system properties.
749 * <p>
750 * The first argument is treated as the name of a system property to
751 * be obtained. The string value of this property is then interpreted
752 * as an integer which is then converted to a <code>Color</code>
753 * object.
754 * <p>
755 * If the specified property is not found or cannot be parsed as
756 * an integer then the <code>Color</code> specified by the second
757 * argument is returned instead.
758 * @param nm the name of the color property
759 * @param v the default <code>Color</code>
760 * @return the <code>Color</code> converted from the system
761 * property, or the specified <code>Color</code>.
762 * @see java.lang.System#getProperty(java.lang.String)
763 * @see java.lang.Integer#getInteger(java.lang.String)
764 * @see java.awt.Color#Color(int)
765 * @since JDK1.0
766 */
767 public static Color getColor(String nm, Color v) {
768 Integer intval = Integer.getInteger(nm);
769 if (intval == null) {
770 return v;
771 }
772 int i = intval.intValue();
773 return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
774 }
775
776 /**
777 * Finds a color in the system properties.
778 * <p>
779 * The first argument is treated as the name of a system property to
780 * be obtained. The string value of this property is then interpreted
781 * as an integer which is then converted to a <code>Color</code>
782 * object.
783 * <p>
784 * If the specified property is not found or could not be parsed as
785 * an integer then the integer value <code>v</code> is used instead,
786 * and is converted to a <code>Color</code> object.
787 * @param nm the name of the color property
788 * @param v the default color value, as an integer
789 * @return the <code>Color</code> converted from the system
790 * property or the <code>Color</code> converted from
791 * the specified integer.
792 * @see java.lang.System#getProperty(java.lang.String)
793 * @see java.lang.Integer#getInteger(java.lang.String)
794 * @see java.awt.Color#Color(int)
795 * @since JDK1.0
796 */
797 public static Color getColor(String nm, int v) {
798 Integer intval = Integer.getInteger(nm);
799 int i = (intval != null) ? intval.intValue() : v;
800 return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, (i >> 0) & 0xFF);
801 }
802
803 /**
804 * Converts the components of a color, as specified by the HSB
805 * model, to an equivalent set of values for the default RGB model.
806 * <p>
807 * The <code>saturation</code> and <code>brightness</code> components
808 * should be floating-point values between zero and one
809 * (numbers in the range 0.0-1.0). The <code>hue</code> component
810 * can be any floating-point number. The floor of this number is
811 * subtracted from it to create a fraction between 0 and 1. This
812 * fractional number is then multiplied by 360 to produce the hue
813 * angle in the HSB color model.
814 * <p>
815 * The integer that is returned by <code>HSBtoRGB</code> encodes the
816 * value of a color in bits 0-23 of an integer value that is the same
817 * format used by the method {@link #getRGB() <code>getRGB</code>}.
818 * This integer can be supplied as an argument to the
819 * <code>Color</code> constructor that takes a single integer argument.
820 * @param hue the hue component of the color
821 * @param saturation the saturation of the color
822 * @param brightness the brightness of the color
823 * @return the RGB value of the color with the indicated hue,
824 * saturation, and brightness.
825 * @see java.awt.Color#getRGB()
826 * @see java.awt.Color#Color(int)
827 * @see java.awt.image.ColorModel#getRGBdefault()
828 * @since JDK1.0
829 */
830 public static int HSBtoRGB(float hue, float saturation, float brightness) {
831 int r = 0, g = 0, b = 0;
832 if (saturation == 0) {
833 r = g = b = (int) (brightness * 255.0f + 0.5f);
834 } else {
835 float h = (hue - (float)Math.floor(hue)) * 6.0f;
836 float f = h - (float)java.lang.Math.floor(h);
837 float p = brightness * (1.0f - saturation);
838 float q = brightness * (1.0f - saturation * f);
839 float t = brightness * (1.0f - (saturation * (1.0f - f)));
840 switch ((int) h) {
841 case 0:
842 r = (int) (brightness * 255.0f + 0.5f);
843 g = (int) (t * 255.0f + 0.5f);
844 b = (int) (p * 255.0f + 0.5f);
845 break;
846 case 1:
847 r = (int) (q * 255.0f + 0.5f);
848 g = (int) (brightness * 255.0f + 0.5f);
849 b = (int) (p * 255.0f + 0.5f);
850 break;
851 case 2:
852 r = (int) (p * 255.0f + 0.5f);
853 g = (int) (brightness * 255.0f + 0.5f);
854 b = (int) (t * 255.0f + 0.5f);
855 break;
856 case 3:
857 r = (int) (p * 255.0f + 0.5f);
858 g = (int) (q * 255.0f + 0.5f);
859 b = (int) (brightness * 255.0f + 0.5f);
860 break;
861 case 4:
862 r = (int) (t * 255.0f + 0.5f);
863 g = (int) (p * 255.0f + 0.5f);
864 b = (int) (brightness * 255.0f + 0.5f);
865 break;
866 case 5:
867 r = (int) (brightness * 255.0f + 0.5f);
868 g = (int) (p * 255.0f + 0.5f);
869 b = (int) (q * 255.0f + 0.5f);
870 break;
871 }
872 }
873 return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
874 }
875
876 /**
877 * Converts the components of a color, as specified by the default RGB
878 * model, to an equivalent set of values for hue, saturation, and
879 * brightness that are the three components of the HSB model.
880 * <p>
881 * If the <code>hsbvals</code> argument is <code>null</code>, then a
882 * new array is allocated to return the result. Otherwise, the method
883 * returns the array <code>hsbvals</code>, with the values put into
884 * that array.
885 * @param r the red component of the color
886 * @param g the green component of the color
887 * @param b the blue component of the color
888 * @param hsbvals the array used to return the
889 * three HSB values, or <code>null</code>
890 * @return an array of three elements containing the hue, saturation,
891 * and brightness (in that order), of the color with
892 * the indicated red, green, and blue components.
893 * @see java.awt.Color#getRGB()
894 * @see java.awt.Color#Color(int)
895 * @see java.awt.image.ColorModel#getRGBdefault()
896 * @since JDK1.0
897 */
898 public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
899 float hue, saturation, brightness;
900 if (hsbvals == null) {
901 hsbvals = new float[3];
902 }
903 int cmax = (r > g) ? r : g;
904 if (b > cmax) cmax = b;
905 int cmin = (r < g) ? r : g;
906 if (b < cmin) cmin = b;
907
908 brightness = ((float) cmax) / 255.0f;
909 if (cmax != 0)
910 saturation = ((float) (cmax - cmin)) / ((float) cmax);
911 else
912 saturation = 0;
913 if (saturation == 0)
914 hue = 0;
915 else {
916 float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
917 float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
918 float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
919 if (r == cmax)
920 hue = bluec - greenc;
921 else if (g == cmax)
922 hue = 2.0f + redc - bluec;
923 else
924 hue = 4.0f + greenc - redc;
925 hue = hue / 6.0f;
926 if (hue < 0)
927 hue = hue + 1.0f;
928 }
929 hsbvals[0] = hue;
930 hsbvals[1] = saturation;
931 hsbvals[2] = brightness;
932 return hsbvals;
933 }
934
935 /**
936 * Creates a <code>Color</code> object based on the specified values
937 * for the HSB color model.
938 * <p>
939 * The <code>s</code> and <code>b</code> components should be
940 * floating-point values between zero and one
941 * (numbers in the range 0.0-1.0). The <code>h</code> component
942 * can be any floating-point number. The floor of this number is
943 * subtracted from it to create a fraction between 0 and 1. This
944 * fractional number is then multiplied by 360 to produce the hue
945 * angle in the HSB color model.
946 * @param h the hue component
947 * @param s the saturation of the color
948 * @param b the brightness of the color
949 * @return a <code>Color</code> object with the specified hue,
950 * saturation, and brightness.
951 * @since JDK1.0
952 */
953 public static Color getHSBColor(float h, float s, float b) {
954 return new Color(HSBtoRGB(h, s, b));
955 }
956
957 /**
958 * Returns a <code>float</code> array containing the color and alpha
959 * components of the <code>Color</code>, as represented in the default
960 * sRGB color space.
961 * If <code>compArray</code> is <code>null</code>, an array of length
962 * 4 is created for the return value. Otherwise,
963 * <code>compArray</code> must have length 4 or greater,
964 * and it is filled in with the components and returned.
965 * @param compArray an array that this method fills with
966 * color and alpha components and returns
967 * @return the RGBA components in a <code>float</code> array.
968 */
969 public float[] getRGBComponents(float[] compArray) {
970 float[] f;
971 if (compArray == null) {
972 f = new float[4];
973 } else {
974 f = compArray;
975 }
976 if (frgbvalue == null) {
977 f[0] = ((float)getRed())/255f;
978 f[1] = ((float)getGreen())/255f;
979 f[2] = ((float)getBlue())/255f;
980 f[3] = ((float)getAlpha())/255f;
981 } else {
982 f[0] = frgbvalue[0];
983 f[1] = frgbvalue[1];
984 f[2] = frgbvalue[2];
985 f[3] = falpha;
986 }
987 return f;
988 }
989
990 /**
991 * Returns a <code>float</code> array containing only the color
992 * components of the <code>Color</code>, in the default sRGB color
993 * space. If <code>compArray</code> is <code>null</code>, an array of
994 * length 3 is created for the return value. Otherwise,
995 * <code>compArray</code> must have length 3 or greater, and it is
996 * filled in with the components and returned.
997 * @param compArray an array that this method fills with color
998 * components and returns
999 * @return the RGB components in a <code>float</code> array.
1000 */
1001 public float[] getRGBColorComponents(float[] compArray) {
1002 float[] f;
1003 if (compArray == null) {
1004 f = new float[3];
1005 } else {
1006 f = compArray;
1007 }
1008 if (frgbvalue == null) {
1009 f[0] = ((float)getRed())/255f;
1010 f[1] = ((float)getGreen())/255f;
1011 f[2] = ((float)getBlue())/255f;
1012 } else {
1013 f[0] = frgbvalue[0];
1014 f[1] = frgbvalue[1];
1015 f[2] = frgbvalue[2];
1016 }
1017 return f;
1018 }
1019
1020 /**
1021 * Returns a <code>float</code> array containing the color and alpha
1022 * components of the <code>Color</code>, in the
1023 * <code>ColorSpace</code> of the <code>Color</code>.
1024 * If <code>compArray</code> is <code>null</code>, an array with
1025 * length equal to the number of components in the associated
1026 * <code>ColorSpace</code> plus one is created for
1027 * the return value. Otherwise, <code>compArray</code> must have at
1028 * least this length and it is filled in with the components and
1029 * returned.
1030 * @param compArray an array that this method fills with the color and
1031 * alpha components of this <code>Color</code> in its
1032 * <code>ColorSpace</code> and returns
1033 * @return the color and alpha components in a <code>float</code>
1034 * array.
1035 */
1036 public float[] getComponents(float[] compArray) {
1037 if (fvalue == null)
1038 return getRGBComponents(compArray);
1039 float[] f;
1040 int n = fvalue.length;
1041 if (compArray == null) {
1042 f = new float[n + 1];
1043 } else {
1044 f = compArray;
1045 }
1046 for (int i = 0; i < n; i++) {
1047 f[i] = fvalue[i];
1048 }
1049 f[n] = falpha;
1050 return f;
1051 }
1052
1053 /**
1054 * Returns a <code>float</code> array containing only the color
1055 * components of the <code>Color</code>, in the
1056 * <code>ColorSpace</code> of the <code>Color</code>.
1057 * If <code>compArray</code> is <code>null</code>, an array with
1058 * length equal to the number of components in the associated
1059 * <code>ColorSpace</code> is created for
1060 * the return value. Otherwise, <code>compArray</code> must have at
1061 * least this length and it is filled in with the components and
1062 * returned.
1063 * @param compArray an array that this method fills with the color
1064 * components of this <code>Color</code> in its
1065 * <code>ColorSpace</code> and returns
1066 * @return the color components in a <code>float</code> array.
1067 */
1068 public float[] getColorComponents(float[] compArray) {
1069 if (fvalue == null)
1070 return getRGBColorComponents(compArray);
1071 float[] f;
1072 int n = fvalue.length;
1073 if (compArray == null) {
1074 f = new float[n];
1075 } else {
1076 f = compArray;
1077 }
1078 for (int i = 0; i < n; i++) {
1079 f[i] = fvalue[i];
1080 }
1081 return f;
1082 }
1083
1084 /**
1085 * Returns a <code>float</code> array containing the color and alpha
1086 * components of the <code>Color</code>, in the
1087 * <code>ColorSpace</code> specified by the <code>cspace</code>
1088 * parameter. If <code>compArray</code> is <code>null</code>, an
1089 * array with length equal to the number of components in
1090 * <code>cspace</code> plus one is created for the return value.
1091 * Otherwise, <code>compArray</code> must have at least this
1092 * length, and it is filled in with the components and returned.
1093 * @param cspace a specified <code>ColorSpace</code>
1094 * @param compArray an array that this method fills with the
1095 * color and alpha components of this <code>Color</code> in
1096 * the specified <code>ColorSpace</code> and returns
1097 * @return the color and alpha components in a <code>float</code>
1098 * array.
1099 */
1100 public float[] getComponents(ColorSpace cspace, float[] compArray) {
1101 if (cs == null) {
1102 cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1103 }
1104 float f[];
1105 if (fvalue == null) {
1106 f = new float[3];
1107 f[0] = ((float)getRed())/255f;
1108 f[1] = ((float)getGreen())/255f;
1109 f[2] = ((float)getBlue())/255f;
1110 } else {
1111 f = fvalue;
1112 }
1113 float tmp[] = cs.toCIEXYZ(f);
1114 float tmpout[] = cspace.fromCIEXYZ(tmp);
1115 if (compArray == null) {
1116 compArray = new float[tmpout.length + 1];
1117 }
1118 for (int i = 0 ; i < tmpout.length ; i++) {
1119 compArray[i] = tmpout[i];
1120 }
1121 if (fvalue == null) {
1122 compArray[tmpout.length] = ((float)getAlpha())/255f;
1123 } else {
1124 compArray[tmpout.length] = falpha;
1125 }
1126 return compArray;
1127 }
1128
1129 /**
1130 * Returns a <code>float</code> array containing only the color
1131 * components of the <code>Color</code> in the
1132 * <code>ColorSpace</code> specified by the <code>cspace</code>
1133 * parameter. If <code>compArray</code> is <code>null</code>, an array
1134 * with length equal to the number of components in
1135 * <code>cspace</code> is created for the return value. Otherwise,
1136 * <code>compArray</code> must have at least this length, and it is
1137 * filled in with the components and returned.
1138 * @param cspace a specified <code>ColorSpace</code>
1139 * @param compArray an array that this method fills with the color
1140 * components of this <code>Color</code> in the specified
1141 * <code>ColorSpace</code>
1142 * @return the color components in a <code>float</code> array.
1143 */
1144 public float[] getColorComponents(ColorSpace cspace, float[] compArray) {
1145 if (cs == null) {
1146 cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1147 }
1148 float f[];
1149 if (fvalue == null) {
1150 f = new float[3];
1151 f[0] = ((float)getRed())/255f;
1152 f[1] = ((float)getGreen())/255f;
1153 f[2] = ((float)getBlue())/255f;
1154 } else {
1155 f = fvalue;
1156 }
1157 float tmp[] = cs.toCIEXYZ(f);
1158 float tmpout[] = cspace.fromCIEXYZ(tmp);
1159 if (compArray == null) {
1160 return tmpout;
1161 }
1162 for (int i = 0 ; i < tmpout.length ; i++) {
1163 compArray[i] = tmpout[i];
1164 }
1165 return compArray;
1166 }
1167
1168 /**
1169 * Returns the <code>ColorSpace</code> of this <code>Color</code>.
1170 * @return this <code>Color</code> object's <code>ColorSpace</code>.
1171 */
1172 public ColorSpace getColorSpace() {
1173 if (cs == null) {
1174 cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1175 }
1176 return cs;
1177 }
1178
1179 /**
1180 * Creates and returns a {@link PaintContext} used to
1181 * generate a solid color field pattern.
1182 * See the {@link Paint#createContext specification} of the
1183 * method in the {@link Paint} interface for information
1184 * on null parameter handling.
1185 *
1186 * @param cm the preferred {@link ColorModel} which represents the most convenient
1187 * format for the caller to receive the pixel data, or {@code null}
1188 * if there is no preference.
1189 * @param r the device space bounding box
1190 * of the graphics primitive being rendered.
1191 * @param r2d the user space bounding box
1192 * of the graphics primitive being rendered.
1193 * @param xform the {@link AffineTransform} from user
1194 * space into device space.
1195 * @param hints the set of hints that the context object can use to
1196 * choose between rendering alternatives.
1197 * @return the {@code PaintContext} for
1198 * generating color patterns.
1199 * @see Paint
1200 * @see PaintContext
1201 * @see ColorModel
1202 * @see Rectangle
1203 * @see Rectangle2D
1204 * @see AffineTransform
1205 * @see RenderingHints
1206 */
1207 public synchronized PaintContext createContext(ColorModel cm, Rectangle r,
1208 Rectangle2D r2d,
1209 AffineTransform xform,
1210 RenderingHints hints) {
1211 return new ColorPaintContext(getRGB(), cm);
1212 }
1213
1214 /**
1215 * Returns the transparency mode for this <code>Color</code>. This is
1216 * required to implement the <code>Paint</code> interface.
1217 * @return this <code>Color</code> object's transparency mode.
1218 * @see Paint
1219 * @see Transparency
1220 * @see #createContext
1221 */
1222 public int getTransparency() {
1223 int alpha = getAlpha();
1224 if (alpha == 0xff) {
1225 return Transparency.OPAQUE;
1226 }
1227 else if (alpha == 0) {
1228 return Transparency.BITMASK;
1229 }
1230 else {
1231 return Transparency.TRANSLUCENT;
1232 }
1233 }
1234
1235 }