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
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} 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 */
60 public 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