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