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