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 trueif 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 trueif 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 trueif 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