/*
 
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
*
 
* This code is free software; you can redistribute it and/or modify it
 
* under the terms of the GNU General Public License version 2 only, as
 
* published by the Free Software Foundation.
  
Oracle designates this
 
* particular file as subject to the "Classpath" exception as provided
 
* by Oracle in the LICENSE file that accompanied this code.
 
*
 
* This code is distributed in the hope that it will be useful, but WITHOUT
 
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
* FITNESS FOR A PARTICULAR PURPOSE.
  
See the GNU General Public License
 
* version 2 for more details (a copy is included in the LICENSE file that
 
* accompanied this code).
 
*
 
* You should have received a copy of the GNU General Public License version
 
* 2 along with this work; if not, write to the Free Software Foundation,
 
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
*
 
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
* or visit www.oracle.com if you need additional information or have any
 
* questions.
 
*/

package java.awt;

import java.beans.ConstructorProperties;
import java.awt.image.ColorModel;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.color.ColorSpace;

/**
 
* The <code>Color</code> class is used to encapsulate colors in the default
 
* sRGB color space or colors in arbitrary color spaces identified by a
 
* {@link ColorSpace}.
  
Every color has an implicit alpha value of 1.0 or
 
* an explicit one provided in the constructor.
  
The alpha value
 
* defines the transparency of a color and can be represented by
 
* a float value in the range 0.0&nbsp;-&nbsp;1.0 or 0&nbsp;-&nbsp;255.
 
* An alpha value of 1.0 or 255 means that the color is completely
 
* opaque and an alpha value of 0 or 0.0 means that the color is
 
* completely transparent.
 
* When constructing a <code>Color</code> with an explicit alpha or
 
* getting the color/alpha components of a <code>Color</code>, the color
 
* components are never premultiplied by the alpha component.
 
* <p>
 
* The default color space for the Java 2D(tm) API is sRGB, a proposed
 
* standard RGB color space.
  
For further information on sRGB,
 
* see <A href=" http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html">
 
* http://www.w3.org/pub/WWW/Graphics/Color/sRGB.html
 
* </A>.
 
* <p>
 
* @version
     
10 Feb 1997
 
* @author
      
Sami Shaio
 
* @author
      
Arthur van Hoff
 
* @see
         
ColorSpace
 
* @see
         
AlphaComposite
 
*/

public class Color implements Paint, java.io.Serializable {

    
/**
     
* The color white.
  
In the default sRGB space.
     
*/
    
public final static Color white
     
= new Color(255, 255, 255);

    
/**
     
* The color white.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color WHITE = white;

    
/**
     
* The color light gray.
  
In the default sRGB space.
     
*/

    
public final static Color lightGray = new Color(192, 192, 192);

    
/**
     
* The color light gray.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color LIGHT_GRAY = lightGray;

    
/**
     
* The color gray.
  
In the default sRGB space.
     
*/
    
public final static Color gray
      
= new Color(128, 128, 128);

    
/**
     
* The color gray.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color GRAY = gray;

    
/**
     
* The color dark gray.
  
In the default sRGB space.
     
*/
    
public final static Color darkGray
  
= new Color(64, 64, 64);

    
/**
     
* The color dark gray.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color DARK_GRAY = darkGray;

    
/**
     
* The color black.
  
In the default sRGB space.
     
*/
    
public final static Color black
     
= new Color(0, 0, 0);

    
/**
     
* The color black.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color BLACK = black;

    
/**
     
* The color red.
  
In the default sRGB space.
     
*/
    
public final static Color red
       
= new Color(255, 0, 0);

    
/**
     
* The color red.
  
In the default sRGB space.
     
* @since 1.4
     
*/
    
public final static Color RED = red;

    
/**
     
* The color pink.
  
In the default sRGB space.
     
*/
    
public final static Color pink
      
= new Color(255, 175, 175);

    
/**
     
* The color pink.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color PINK = pink;

    
/**
     
* The color orange.
  
In the default sRGB space.
     
*/
    
public final static Color orange
    
= new Color(255, 200, 0);

    
/**
     
* The color orange.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color ORANGE = orange;

    
/**
     
* The color yellow.
  
In the default sRGB space.
     
*/
    
public final static Color yellow
    
= new Color(255, 255, 0);

    
/**
     
* The color yellow.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color YELLOW = yellow;

    
/**
     
* The color green.
  
In the default sRGB space.
     
*/
    
public final static Color green
     
= new Color(0, 255, 0);

    
/**
     
* The color green.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color GREEN = green;

    
/**
     
* The color magenta.
  
In the default sRGB space.
     
*/
    
public final static Color magenta
   
= new Color(255, 0, 255);

    
/**
     
* The color magenta.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color MAGENTA = magenta;

    
/**
     
* The color cyan.
  
In the default sRGB space.
     
*/
    
public final static Color cyan
      
= new Color(0, 255, 255);

    
/**
     
* The color cyan.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color CYAN = cyan;

    
/**
     
* The color blue.
  
In the default sRGB space.
     
*/
    
public final static Color blue
      
= new Color(0, 0, 255);

    
/**
     
* The color blue.
  
In the default sRGB space.
     
* @since 1.4
     
*/

    
public final static Color BLUE = blue;

    
/**
     
* The color value.
     
* @serial
     
* @see #getRGB
     
*/
    
int value;

    
/**
     
* The color value in the default sRGB <code>ColorSpace</code> as
     
* <code>float</code> components (no alpha).
     
* If <code>null</code> after object construction, this must be an
     
* sRGB color constructed with 8-bit precision, so compute from the
     
* <code>int</code> color value.
     
* @serial
     
* @see #getRGBColorComponents
     
* @see #getRGBComponents
     
*/

    
private float frgbvalue[] = null;

    
/**
     
* The color value in the native <code>ColorSpace</code> as
     
* <code>float</code> components (no alpha).
     
* If <code>null</code> after object construction, this must be an
     
* sRGB color constructed with 8-bit precision, so compute from the
     
* <code>int</code> color value.
     
* @serial
     
* @see #getRGBColorComponents
     
* @see #getRGBComponents
     
*/

    
private float fvalue[] = null;

    
/**
     
* The alpha value as a <code>float</code> component.
     
* If <code>frgbvalue</code> is <code>null</code>, this is not valid
     
* data, so compute from the <code>int</code> color value.
     
* @serial
     
* @see #getRGBComponents
     
* @see #getComponents
     
*/

    
private float falpha = 0.0f;

    
/**
     
* The <code>ColorSpace</code>.
  
If <code>null</code>, then it's
     
* default is sRGB.
     
* @serial
     
* @see #getColor
     
* @see #getColorSpace
     
* @see #getColorComponents
     
*/

    
private ColorSpace cs = null;

    
/*
     
* JDK 1.1 serialVersionUID
     
*/
     
private static final long serialVersionUID = 118526816881161077L;

    
/**
     
* Initialize JNI field and method IDs
     
*/
    
private static native void initIDs();

    
static {
        
/** 4112352 - Calling getDefaultToolkit()
         
** here can cause this class to be accessed before it is fully
         
** initialized. DON'T DO IT!!!
         
**
         
** Toolkit.getDefaultToolkit();
         
**/


        
/* ensure that the necessary native libraries are loaded */
        
Toolkit.loadLibraries();
        
if (!GraphicsEnvironment.isHeadless()) {
            
initIDs();
        
}
    
}

    
/**
     
* Checks the color integer components supplied for validity.
     
* Throws an {@link IllegalArgumentException} if the value is out of
     
* range.
     
* @param r the Red component
     
* @param g the Green component
     
* @param b the Blue component
     
**/

    
private static void testColorValueRange(int r, int g, int b, int a) {
        
boolean rangeError = false;
        
String badComponentString = "";

        
if ( a < 0 || a > 255) {
            
rangeError = true;
            
badComponentString = badComponentString + " Alpha";
        
}
        
if ( r < 0 || r > 255) {
            
rangeError = true;
            
badComponentString = badComponentString + " Red";
        
}
        
if ( g < 0 || g > 255) {
            
rangeError = true;
            
badComponentString = badComponentString + " Green";
        
}
        
if ( b < 0 || b > 255) {
            
rangeError = true;
            
badComponentString = badComponentString + " Blue";
        
}
        
if ( rangeError == true ) {
        
throw new IllegalArgumentException("Color parameter outside of expected range:"
                                           
+ badComponentString);
        
}
    
}

    
/**
     
* Checks the color <code>float</code> components supplied for
     
* validity.
     
* Throws an <code>IllegalArgumentException</code> if the value is out
     
* of range.
     
* @param r the Red component
     
* @param g the Green component
     
* @param b the Blue component
     
**/

    
private static void testColorValueRange(float r, float g, float b, float a) {
        
boolean rangeError = false;
        
String badComponentString = "";
        
if ( a < 0.0 || a > 1.0) {
            
rangeError = true;
            
badComponentString = badComponentString + " Alpha";
        
}
        
if ( r < 0.0 || r > 1.0) {
            
rangeError = true;
            
badComponentString = badComponentString + " Red";
        
}
        
if ( g < 0.0 || g > 1.0) {
            
rangeError = true;
            
badComponentString = badComponentString + " Green";
        
}
        
if ( b < 0.0 || b > 1.0) {
            
rangeError = true;
            
badComponentString = badComponentString + " Blue";
        
}
        
if ( rangeError == true ) {
        
throw new IllegalArgumentException("Color parameter outside of expected range:"
                                           
+ badComponentString);
        
}
    
}

    
/**
     
* Creates an opaque sRGB color with the specified red, green,
     
* and blue values in the range (0 - 255).
     
* The actual color used in rendering depends
     
* on finding the best match given the color space
     
* available for a given output device.
     
* Alpha is defaulted to 255.
     
*
     
* @throws IllegalArgumentException if <code>r</code>, <code>g</code>
     
*
        
or <code>b</code> are outside of the range
     
*
        
0 to 255, inclusive
     
* @param r the red component
     
* @param g the green component
     
* @param b the blue component
     
* @see #getRed
     
* @see #getGreen
     
* @see #getBlue
     
* @see #getRGB
     
*/

    
public Color(int r, int g, int b) {
        
this(r, g, b, 255);
    
}

    
/**
     
* Creates an sRGB color with the specified red, green, blue, and alpha
     
* values in the range (0 - 255).
     
*
     
* @throws IllegalArgumentException if <code>r</code>, <code>g</code>,
     
*
        
<code>b</code> or <code>a</code> are outside of the range
     
*
        
0 to 255, inclusive
     
* @param r the red component
     
* @param g the green component
     
* @param b the blue component
     
* @param a the alpha component
     
* @see #getRed
     
* @see #getGreen
     
* @see #getBlue
     
* @see #getAlpha
     
* @see #getRGB
     
*/

    
@ConstructorProperties({"red", "green", "blue", "alpha"})
    
public Color(int r, int g, int b, int a) {
        
value = ((a & 0xFF) << 24) |
                
((r & 0xFF) << 16) |
                
((g & 0xFF) << 8)
  
|
                
((b & 0xFF) << 0);
        
testColorValueRange(r,g,b,a);
    
}

    
/**
     
* Creates an opaque sRGB color with the specified combined RGB value
     
* consisting of the red component in bits 16-23, the green component
     
* in bits 8-15, and the blue component in bits 0-7.
  
The actual color
     
* used in rendering depends on finding the best match given the
     
* color space available for a particular output device.
  
Alpha is
     
* defaulted to 255.
     
*
     
* @param rgb the combined RGB components
     
* @see java.awt.image.ColorModel#getRGBdefault
     
* @see #getRed
     
* @see #getGreen
     
* @see #getBlue
     
* @see #getRGB
     
*/

    
public Color(int rgb) {
        
value = 0xff000000 | rgb;
    
}

    
/**
     
* Creates an sRGB color with the specified combined RGBA value consisting
     
* of the alpha component in bits 24-31, the red component in bits 16-23,
     
* the green component in bits 8-15, and the blue component in bits 0-7.
     
* If the <code>hasalpha</code> argument is <code>false</code>, alpha
     
* is defaulted to 255.
     
*
     
* @param rgba the combined RGBA components
     
* @param hasalpha <code>true</code> if the alpha bits are valid;
     
*
        
<code>false</code> otherwise
     
* @see java.awt.image.ColorModel#getRGBdefault
     
* @see #getRed
     
* @see #getGreen
     
* @see #getBlue
     
* @see #getAlpha
     
* @see #getRGB
     
*/

    
public Color(int rgba, boolean hasalpha) {
        
if (hasalpha) {
            
value = rgba;
        
} else {
            
value = 0xff000000 | rgba;
        
}
    
}

    
/**
     
* Creates an opaque sRGB color with the specified red, green, and blue
     
* values in the range (0.0 - 1.0).
  
Alpha is defaulted to 1.0.The
     
* actual color used in rendering depends on finding the best
     
* match given the color space available for a particular output
     
* device.
     
*
     
* @throws IllegalArgumentException if <code>r</code>, <code>g</code>
     
*
        
or <code>b</code> are outside of the range
     
*
        
0.0 to 1.0, inclusive
     
* @param r the red component
     
* @param g the green component
     
* @param b the blue component
     
* @see #getRed
     
* @see #getGreen
     
* @see #getBlue
     
* @see #getRGB
     
*/

    
public Color(float r, float g, float b) {
        
this( (int) (r*255+0.5), (int) (g*255+0.5), (int) (b*255+0.5));
        
testColorValueRange(r,g,b,1.0f);
        
frgbvalue = new float[3];
        
frgbvalue[0] = r;
        
frgbvalue[1] = g;
        
frgbvalue[2] = b;
        
falpha = 1.0f;
        
fvalue = frgbvalue;
    
}

    
/**
     
* Creates an sRGB color with the specified red, green, blue, and
     
* alpha values in the range (0.0 - 1.0).
  
The actual color
     
* used in rendering depends on finding the best match given the
     
* color space available for a particular output device.
     
* @throws IllegalArgumentException if <code>r</code>, <code>g</code>
     
*
        
<code>b</code> or <code>a</code> are outside of the range
     
*
        
0.0 to 1.0, inclusive
     
* @param r the red component
     
* @param g the green component
     
* @param b the blue component
     
* @param a the alpha component
     
* @see #getRed
     
* @see #getGreen
     
* @see #getBlue
     
* @see #getAlpha
     
* @see #getRGB
     
*/

    
public Color(float r, float g, float b, float a) {
        
this((int)(r*255+0.5), (int)(g*255+0.5), (int)(b*255+0.5), (int)(a*255+0.5));
        
frgbvalue = new float[3];
        
frgbvalue[0] = r;
        
frgbvalue[1] = g;
        
frgbvalue[2] = b;
        
falpha = a;
        
fvalue = frgbvalue;
    
}

    
/**
     
* Creates a color in the specified <code>ColorSpace</code>
     
* with the color components specified in the <code>float</code>
     
* array and the specified alpha.
  
The number of components is
     
* determined by the type of the <code>ColorSpace</code>.
  
For
     
* example, RGB requires 3 components, but CMYK requires 4
     
* components.
     
* @param cspace the <code>ColorSpace</code> to be used to
     
*
                  
interpret the components
     
* @param components an arbitrary number of color components
     
*
                      
that is compatible with the <code>ColorSpace</code>
     
* @param alpha alpha value
     
* @throws IllegalArgumentException if any of the values in the
     
*
         
<code>components</code> array or <code>alpha</code> is
     
*
         
outside of the range 0.0 to 1.0
     
* @see #getComponents
     
* @see #getColorComponents
     
*/

    
public Color(ColorSpace cspace, float components[], float alpha) {
        
boolean rangeError = false;
        
String badComponentString = "";
        
int n = cspace.getNumComponents();
        
fvalue = new float[n];
        
for (int i = 0; i < n; i++) {
            
if (components[i] < 0.0 || components[i] > 1.0) {
                
rangeError = true;
                
badComponentString = badComponentString + "Component " + i
                                     
+ " ";
            
} else {
                
fvalue[i] = components[i];
            
}
        
}
        
if (alpha < 0.0 || alpha > 1.0) {
            
rangeError = true;
            
badComponentString = badComponentString + "Alpha";
        
} else {
            
falpha = alpha;
        
}
        
if (rangeError) {
            
throw new IllegalArgumentException(
                
"Color parameter outside of expected range: " +
                
badComponentString);
        
}
        
frgbvalue = cspace.toRGB(fvalue);
        
cs = cspace;
        
value = ((((int)(falpha*255)) & 0xFF) << 24) |
                
((((int)(frgbvalue[0]*255)) & 0xFF) << 16) |
                
((((int)(frgbvalue[1]*255)) & 0xFF) << 8)
  
|
                
((((int)(frgbvalue[2]*255)) & 0xFF) << 0);
    
}

    
/**
     
* Returns the red component in the range 0-255 in the default sRGB
     
* space.
     
* @return the red component.
     
* @see #getRGB
     
*/

    
public int getRed() {
        
return (getRGB() >> 16) & 0xFF;
    
}

    
/**
     
* Returns the green component in the range 0-255 in the default sRGB
     
* space.
     
* @return the green component.
     
* @see #getRGB
     
*/

    
public int getGreen() {
        
return (getRGB() >> 8) & 0xFF;
    
}

    
/**
     
* Returns the blue component in the range 0-255 in the default sRGB
     
* space.
     
* @return the blue component.
     
* @see #getRGB
     
*/

    
public int getBlue() {
        
return (getRGB() >> 0) & 0xFF;
    
}

    
/**
     
* Returns the alpha component in the range 0-255.
     
* @return the alpha component.
     
* @see #getRGB
     
*/

    
public int getAlpha() {
        
return (getRGB() >> 24) & 0xff;
    
}

    
/**
     
* Returns the RGB value representing the color in the default sRGB
     
* {@link ColorModel}.
     
* (Bits 24-31 are alpha, 16-23 are red, 8-15 are green, 0-7 are
     
* blue).
     
* @return the RGB value of the color in the default sRGB
     
*
         
<code>ColorModel</code>.
     
* @see java.awt.image.ColorModel#getRGBdefault
     
* @see #getRed
     
* @see #getGreen
     
* @see #getBlue
     
* @since JDK1.0
     
*/

    
public int getRGB() {
        
return value;
    
}

    
private static final double FACTOR = 0.7;

    
/**
     
* Creates a new <code>Color</code> that is a brighter version of this
     
* <code>Color</code>.
     
* <p>
     
* This method applies an arbitrary scale factor to each of the three RGB
     
* components of this <code>Color</code> to create a brighter version
     
* of this <code>Color</code>.
     
* The {@code alpha} value is preserved.
     
* Although <code>brighter</code> and
     
* <code>darker</code> are inverse operations, the results of a
     
* series of invocations of these two methods might be inconsistent
     
* because of rounding errors.
     
* @returna new <code>Color</code> object that is
     
*
                 
a brighter version of this <code>Color</code>
     
*
                 
with the same {@code alpha} value.
     
* @see
        
java.awt.Color#darker
     
* @since
      
JDK1.0
     
*/

    
public Color brighter() {
        
int r = getRed();
        
int g = getGreen();
        
int b = getBlue();
        
int alpha = getAlpha();

        
/* From 2D group:
         
* 1. black.brighter() should return grey
         
* 2. applying brighter to blue will always return blue, brighter
         
* 3. non pure color (non zero rgb) will eventually return white
         
*/

        
int i = (int)(1.0/(1.0-FACTOR));
        
if ( r == 0 && g == 0 && b == 0) {
            
return new Color(i, i, i, alpha);
        
}
        
if ( r > 0 && r < i ) r = i;
        
if ( g > 0 && g < i ) g = i;
        
if ( b > 0 && b < i ) b = i;

        
return new Color(Math.min((int)(r/FACTOR), 255),
                         
Math.min((int)(g/FACTOR), 255),
                         
Math.min((int)(b/FACTOR), 255),
                         
alpha);
    
}

    
/**
     
* Creates a new <code>Color</code> that is a darker version of this
     
* <code>Color</code>.
     
* <p>
     
* This method applies an arbitrary scale factor to each of the three RGB
     
* components of this <code>Color</code> to create a darker version of
     
* this <code>Color</code>.
     
* The {@code alpha} value is preserved.
     
* Although <code>brighter</code> and
     
* <code>darker</code> are inverse operations, the results of a series
     
* of invocations of these two methods might be inconsistent because
     
* of rounding errors.
     
* @return
  
a new <code>Color</code> object that is
     
*
                    
a darker version of this <code>Color</code>
     
*
                    
with the same {@code alpha} value.
     
* @see
        
java.awt.Color#brighter
     
* @since
      
JDK1.0
     
*/

    
public Color darker() {
        
return new Color(Math.max((int)(getRed()
  
*FACTOR), 0),
                         
Math.max((int)(getGreen()*FACTOR), 0),
                         
Math.max((int)(getBlue() *FACTOR), 0),
                         
getAlpha());
    
}

    
/**
     
* Computes the hash code for this <code>Color</code>.
     
* @returna hash code value for this object.
     
* @since
      
JDK1.0
     
*/

    
public int hashCode() {
        
return value;
    
}

    
/**
     
* Determines whether another object is equal to this
     
* <code>Color</code>.
     
* <p>
     
* The result is <code>true</code> if and only if the argument is not
     
* <code>null</code> and is a <code>Color</code> object that has the same
     
* red, green, blue, and alpha values as this object.
     
* @param
       
obj
   
the object to test for equality with this
     
*
                          
<code>Color</code>
     
* @return
      
<code>true</code> if the objects are the same;
     
*
                             
<code>false</code> otherwise.
     
* @since
   
JDK1.0
     
*/

    
public boolean equals(Object obj) {
        
return obj instanceof Color && ((Color)obj).getRGB() == this.getRGB();
    
}

    
/**
     
* Returns a string representation of this <code>Color</code>. This
     
* method is intended to be used only for debugging purposes.
  
The
     
* content and format of the returned string might vary between
     
* implementations. The returned string might be empty but cannot
     
* be <code>null</code>.
     
*
     
* @return
  
a string representation of this <code>Color</code>.
     
*/

    
public String toString() {
        
return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]";
    
}

    
/**
     
* Converts a <code>String</code> to an integer and returns the
     
* specified opaque <code>Color</code>. This method handles string
     
* formats that are used to represent octal and hexadecimal numbers.
     
* @param
      
nm a <code>String</code> that represents
     
*
                            
an opaque color as a 24-bit integer
     
* @returnthe new <code>Color</code> object.
     
* @see
        
java.lang.Integer#decode
     
* @exception
  
NumberFormatExceptionif the specified string cannot
     
*
                      
be interpreted as a decimal,
     
*
                      
octal, or hexadecimal integer.
     
* @since
      
JDK1.1
     
*/

    
public static Color decode(String nm) throws NumberFormatException {
        
Integer intval = Integer.decode(nm);
        
int i = intval.intValue();
        
return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
    
}

    
/**
     
* Finds a color in the system properties.
     
* <p>
     
* The argument is treated as the name of a system property to
     
* be obtained. The string value of this property is then interpreted
     
* as an integer which is then converted to a <code>Color</code>
     
* object.
     
* <p>
     
* If the specified property is not found or could not be parsed as
     
* an integer then <code>null</code> is returned.
     
* @param
    
nm the name of the color property
     
* @return
   
the <code>Color</code> converted from the system
     
*
          
property.
     
* @see
      
java.lang.System#getProperty(java.lang.String)
     
* @see
      
java.lang.Integer#getInteger(java.lang.String)
     
* @see
      
java.awt.Color#Color(int)
     
* @since
    
JDK1.0
     
*/

    
public static Color getColor(String nm) {
        
return getColor(nm, null);
    
}

    
/**
     
* Finds a color in the system properties.
     
* <p>
     
* The first argument is treated as the name of a system property to
     
* be obtained. The string value of this property is then interpreted
     
* as an integer which is then converted to a <code>Color</code>
     
* object.
     
* <p>
     
* If the specified property is not found or cannot be parsed as
     
* an integer then the <code>Color</code> specified by the second
     
* argument is returned instead.
     
* @param
    
nm the name of the color property
     
* @param
    
vthe default <code>Color</code>
     
* @return
   
the <code>Color</code> converted from the system
     
*
          
property, or the specified <code>Color</code>.
     
* @see
      
java.lang.System#getProperty(java.lang.String)
     
* @see
      
java.lang.Integer#getInteger(java.lang.String)
     
* @see
      
java.awt.Color#Color(int)
     
* @since
    
JDK1.0
     
*/

    
public static Color getColor(String nm, Color v) {
        
Integer intval = Integer.getInteger(nm);
        
if (intval == null) {
            
return v;
        
}
        
int i = intval.intValue();
        
return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
    
}

    
/**
     
* Finds a color in the system properties.
     
* <p>
     
* The first argument is treated as the name of a system property to
     
* be obtained. The string value of this property is then interpreted
     
* as an integer which is then converted to a <code>Color</code>
     
* object.
     
* <p>
     
* If the specified property is not found or could not be parsed as
     
* an integer then the integer value <code>v</code> is used instead,
     
* and is converted to a <code>Color</code> object.
     
* @param
    
nm
  
the name of the color property
     
* @param
    
v
   
the default color value, as an integer
     
* @return
   
the <code>Color</code> converted from the system
     
*
          
property or the <code>Color</code> converted from
     
*
          
the specified integer.
     
* @see
      
java.lang.System#getProperty(java.lang.String)
     
* @see
      
java.lang.Integer#getInteger(java.lang.String)
     
* @see
      
java.awt.Color#Color(int)
     
* @since
    
JDK1.0
     
*/

    
public static Color getColor(String nm, int v) {
        
Integer intval = Integer.getInteger(nm);
        
int i = (intval != null) ? intval.intValue() : v;
        
return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, (i >> 0) & 0xFF);
    
}

    
/**
     
* Converts the components of a color, as specified by the HSB
     
* model, to an equivalent set of values for the default RGB model.
     
* <p>
     
* The <code>saturation</code> and <code>brightness</code> components
     
* should be floating-point values between zero and one
     
* (numbers in the range 0.0-1.0).
  
The <code>hue</code> component
     
* can be any floating-point number.
  
The floor of this number is
     
* subtracted from it to create a fraction between 0 and 1.
  
This
     
* fractional number is then multiplied by 360 to produce the hue
     
* angle in the HSB color model.
     
* <p>
     
* The integer that is returned by <code>HSBtoRGB</code> encodes the
     
* value of a color in bits 0-23 of an integer value that is the same
     
* format used by the method {@link #getRGB() getRGB}.
     
* This integer can be supplied as an argument to the
     
* <code>Color</code> constructor that takes a single integer argument.
     
* @paramhue
   
the hue component of the color
     
* @paramsaturation
   
the saturation of the color
     
* @parambrightness
   
the brightness of the color
     
* @return
    
the RGB value of the color with the indicated hue,
     
*
                            
saturation, and brightness.
     
* @see
       
java.awt.Color#getRGB()
     
* @see
       
java.awt.Color#Color(int)
     
* @see
       
java.awt.image.ColorModel#getRGBdefault()
     
* @sinceJDK1.0
     
*/

    
public static int HSBtoRGB(float hue, float saturation, float brightness) {
        
int r = 0, g = 0, b = 0;
        
if (saturation == 0) {
            
r = g = b = (int) (brightness * 255.0f + 0.5f);
        
} else {
            
float h = (hue - (float)Math.floor(hue)) * 6.0f;
            
float f = h - (float)java.lang.Math.floor(h);
            
float p = brightness * (1.0f - saturation);
            
float q = brightness * (1.0f - saturation * f);
            
float t = brightness * (1.0f - (saturation * (1.0f - f)));
            
switch ((int) h) {
            
case 0:
                
r = (int) (brightness * 255.0f + 0.5f);
                
g = (int) (t * 255.0f + 0.5f);
                
b = (int) (p * 255.0f + 0.5f);
                
break;
            
case 1:
                
r = (int) (q * 255.0f + 0.5f);
                
g = (int) (brightness * 255.0f + 0.5f);
                
b = (int) (p * 255.0f + 0.5f);
                
break;
            
case 2:
                
r = (int) (p * 255.0f + 0.5f);
                
g = (int) (brightness * 255.0f + 0.5f);
                
b = (int) (t * 255.0f + 0.5f);
                
break;
            
case 3:
                
r = (int) (p * 255.0f + 0.5f);
                
g = (int) (q * 255.0f + 0.5f);
                
b = (int) (brightness * 255.0f + 0.5f);
                
break;
            
case 4:
                
r = (int) (t * 255.0f + 0.5f);
                
g = (int) (p * 255.0f + 0.5f);
                
b = (int) (brightness * 255.0f + 0.5f);
                
break;
            
case 5:
                
r = (int) (brightness * 255.0f + 0.5f);
                
g = (int) (p * 255.0f + 0.5f);
                
b = (int) (q * 255.0f + 0.5f);
                
break;
            
}
        
}
        
return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
    
}

    
/**
     
* Converts the components of a color, as specified by the default RGB
     
* model, to an equivalent set of values for hue, saturation, and
     
* brightness that are the three components of the HSB model.
     
* <p>
     
* If the <code>hsbvals</code> argument is <code>null</code>, then a
     
* new array is allocated to return the result. Otherwise, the method
     
* returns the array <code>hsbvals</code>, with the values put into
     
* that array.
     
* @paramr
   
the red component of the color
     
* @paramg
   
the green component of the color
     
* @paramb
   
the blue component of the color
     
* @paramhsbvals
  
the array used to return the
     
*
                     
three HSB values, or <code>null</code>
     
* @return
    
an array of three elements containing the hue, saturation,
     
*
                     
and brightness (in that order), of the color with
     
*
                     
the indicated red, green, and blue components.
     
* @see
       
java.awt.Color#getRGB()
     
* @see
       
java.awt.Color#Color(int)
     
* @see
       
java.awt.image.ColorModel#getRGBdefault()
     
* @sinceJDK1.0
     
*/

    
public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
        
float hue, saturation, brightness;
        
if (hsbvals == null) {
            
hsbvals = new float[3];
        
}
        
int cmax = (r > g) ? r : g;
        
if (b > cmax) cmax = b;
        
int cmin = (r < g) ? r : g;
        
if (b < cmin) cmin = b;

        
brightness = ((float) cmax) / 255.0f;
        
if (cmax != 0)
            
saturation = ((float) (cmax - cmin)) / ((float) cmax);
        
else
            
saturation = 0;
        
if (saturation == 0)
            
hue = 0;
        
else {
            
float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
            
float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
            
float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
            
if (r == cmax)
                
hue = bluec - greenc;
            
else if (g == cmax)
                
hue = 2.0f + redc - bluec;
            
else
                
hue = 4.0f + greenc - redc;
            
hue = hue / 6.0f;
            
if (hue < 0)
                
hue = hue + 1.0f;
        
}
        
hsbvals[0] = hue;
        
hsbvals[1] = saturation;
        
hsbvals[2] = brightness;
        
return hsbvals;
    
}

    
/**
     
* Creates a <code>Color</code> object based on the specified values
     
* for the HSB color model.
     
* <p>
     
* The <code>s</code> and <code>b</code> components should be
     
* floating-point values between zero and one
     
* (numbers in the range 0.0-1.0).
  
The <code>h</code> component
     
* can be any floating-point number.
  
The floor of this number is
     
* subtracted from it to create a fraction between 0 and 1.
  
This
     
* fractional number is then multiplied by 360 to produce the hue
     
* angle in the HSB color model.
     
* @param
  
h
   
the hue component
     
* @param
  
s
   
the saturation of the color
     
* @param
  
b
   
the brightness of the color
     
* @return
  
a <code>Color</code> object with the specified hue,
     
*
                                 
saturation, and brightness.
     
* @since
   
JDK1.0
     
*/

    
public static Color getHSBColor(float h, float s, float b) {
        
return new Color(HSBtoRGB(h, s, b));
    
}

    
/**
     
* Returns a <code>float</code> array containing the color and alpha
     
* components of the <code>Color</code>, as represented in the default
     
* sRGB color space.
     
* If <code>compArray</code> is <code>null</code>, an array of length
     
* 4 is created for the return value.
  
Otherwise,
     
* <code>compArray</code> must have length 4 or greater,
     
* and it is filled in with the components and returned.
     
* @param compArray an array that this method fills with
     
*
                  
color and alpha components and returns
     
* @return the RGBA components in a <code>float</code> array.
     
*/

    
public float[] getRGBComponents(float[] compArray) {
        
float[] f;
        
if (compArray == null) {
            
f = new float[4];
        
} else {
            
f = compArray;
        
}
        
if (frgbvalue == null) {
            
f[0] = ((float)getRed())/255f;
            
f[1] = ((float)getGreen())/255f;
            
f[2] = ((float)getBlue())/255f;
            
f[3] = ((float)getAlpha())/255f;
        
} else {
            
f[0] = frgbvalue[0];
            
f[1] = frgbvalue[1];
            
f[2] = frgbvalue[2];
            
f[3] = falpha;
        
}
        
return f;
    
}

    
/**
     
* Returns a <code>float</code> array containing only the color
     
* components of the <code>Color</code>, in the default sRGB color
     
* space.
  
If <code>compArray</code> is <code>null</code>, an array of
     
* length 3 is created for the return value.
  
Otherwise,
     
* <code>compArray</code> must have length 3 or greater, and it is
     
* filled in with the components and returned.
     
* @param compArray an array that this method fills with color
     
*
          
components and returns
     
* @return the RGB components in a <code>float</code> array.
     
*/

    
public float[] getRGBColorComponents(float[] compArray) {
        
float[] f;
        
if (compArray == null) {
            
f = new float[3];
        
} else {
            
f = compArray;
        
}
        
if (frgbvalue == null) {
            
f[0] = ((float)getRed())/255f;
            
f[1] = ((float)getGreen())/255f;
            
f[2] = ((float)getBlue())/255f;
        
} else {
            
f[0] = frgbvalue[0];
            
f[1] = frgbvalue[1];
            
f[2] = frgbvalue[2];
        
}
        
return f;
    
}

    
/**
     
* Returns a <code>float</code> array containing the color and alpha
     
* components of the <code>Color</code>, in the
     
* <code>ColorSpace</code> of the <code>Color</code>.
     
* If <code>compArray</code> is <code>null</code>, an array with
     
* length equal to the number of components in the associated
     
* <code>ColorSpace</code> plus one is created for
     
* the return value.
  
Otherwise, <code>compArray</code> must have at
     
* least this length and it is filled in with the components and
     
* returned.
     
* @param compArray an array that this method fills with the color and
     
*
          
alpha components of this <code>Color</code> in its
     
*
          
<code>ColorSpace</code> and returns
     
* @return the color and alpha components in a <code>float</code>
     
*
          
array.
     
*/

    
public float[] getComponents(float[] compArray) {
        
if (fvalue == null)
            
return getRGBComponents(compArray);
        
float[] f;
        
int n = fvalue.length;
        
if (compArray == null) {
            
f = new float[n + 1];
        
} else {
            
f = compArray;
        
}
        
for (int i = 0; i < n; i++) {
            
f[i] = fvalue[i];
        
}
        
f[n] = falpha;
        
return f;
    
}

    
/**
     
* Returns a <code>float</code> array containing only the color
     
* components of the <code>Color</code>, in the
     
* <code>ColorSpace</code> of the <code>Color</code>.
     
* If <code>compArray</code> is <code>null</code>, an array with
     
* length equal to the number of components in the associated
     
* <code>ColorSpace</code> is created for
     
* the return value.
  
Otherwise, <code>compArray</code> must have at
     
* least this length and it is filled in with the components and
     
* returned.
     
* @param compArray an array that this method fills with the color
     
*
          
components of this <code>Color</code> in its
     
*
          
<code>ColorSpace</code> and returns
     
* @return the color components in a <code>float</code> array.
     
*/

    
public float[] getColorComponents(float[] compArray) {
        
if (fvalue == null)
            
return getRGBColorComponents(compArray);
        
float[] f;
        
int n = fvalue.length;
        
if (compArray == null) {
            
f = new float[n];
        
} else {
            
f = compArray;
        
}
        
for (int i = 0; i < n; i++) {
            
f[i] = fvalue[i];
        
}
        
return f;
    
}

    
/**
     
* Returns a <code>float</code> array containing the color and alpha
     
* components of the <code>Color</code>, in the
     
* <code>ColorSpace</code> specified by the <code>cspace</code>
     
* parameter.
  
If <code>compArray</code> is <code>null</code>, an
     
* array with length equal to the number of components in
     
* <code>cspace</code> plus one is created for the return value.
     
* Otherwise, <code>compArray</code> must have at least this
     
* length, and it is filled in with the components and returned.
     
* @param cspace a specified <code>ColorSpace</code>
     
* @param compArray an array that this method fills with the
     
*
          
color and alpha components of this <code>Color</code> in
     
*
          
the specified <code>ColorSpace</code> and returns
     
* @return the color and alpha components in a <code>float</code>
     
*
          
array.
     
*/

    
public float[] getComponents(ColorSpace cspace, float[] compArray) {
        
if (cs == null) {
            
cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        
}
        
float f[];
        
if (fvalue == null) {
            
f = new float[3];
            
f[0] = ((float)getRed())/255f;
            
f[1] = ((float)getGreen())/255f;
            
f[2] = ((float)getBlue())/255f;
        
} else {
            
f = fvalue;
        
}
        
float tmp[] = cs.toCIEXYZ(f);
        
float tmpout[] = cspace.fromCIEXYZ(tmp);
        
if (compArray == null) {
            
compArray = new float[tmpout.length + 1];
        
}
        
for (int i = 0 ; i < tmpout.length ; i++) {
            
compArray[i] = tmpout[i];
        
}
        
if (fvalue == null) {
            
compArray[tmpout.length] = ((float)getAlpha())/255f;
        
} else {
            
compArray[tmpout.length] = falpha;
        
}
        
return compArray;
    
}

    
/**
     
* Returns a <code>float</code> array containing only the color
     
* components of the <code>Color</code> in the
     
* <code>ColorSpace</code> specified by the <code>cspace</code>
     
* parameter. If <code>compArray</code> is <code>null</code>, an array
     
* with length equal to the number of components in
     
* <code>cspace</code> is created for the return value.
  
Otherwise,
     
* <code>compArray</code> must have at least this length, and it is
     
* filled in with the components and returned.
     
* @param cspace a specified <code>ColorSpace</code>
     
* @param compArray an array that this method fills with the color
     
*
          
components of this <code>Color</code> in the specified
     
*
          
<code>ColorSpace</code>
     
* @return the color components in a <code>float</code> array.
     
*/

    
public float[] getColorComponents(ColorSpace cspace, float[] compArray) {
        
if (cs == null) {
            
cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        
}
        
float f[];
        
if (fvalue == null) {
            
f = new float[3];
            
f[0] = ((float)getRed())/255f;
            
f[1] = ((float)getGreen())/255f;
            
f[2] = ((float)getBlue())/255f;
        
} else {
            
f = fvalue;
        
}
        
float tmp[] = cs.toCIEXYZ(f);
        
float tmpout[] = cspace.fromCIEXYZ(tmp);
        
if (compArray == null) {
            
return tmpout;
        
}
        
for (int i = 0 ; i < tmpout.length ; i++) {
            
compArray[i] = tmpout[i];
        
}
        
return compArray;
    
}

    
/**
     
* Returns the <code>ColorSpace</code> of this <code>Color</code>.
     
* @return this <code>Color</code> object's <code>ColorSpace</code>.
     
*/

    
public ColorSpace getColorSpace() {
        
if (cs == null) {
            
cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        
}
        
return cs;
    
}

    
/**
     
* Creates and returns a {@link PaintContext} used to
     
* generate a solid color field pattern.
     
* See the {@link Paint#createContext specification} of the
     
* method in the {@link Paint} interface for information
     
* on null parameter handling.
     
*
     
* @param cm the preferred {@link ColorModel} which represents the most convenient
     
*
           
format for the caller to receive the pixel data, or {@code null}
     
*
           
if there is no preference.
     
* @param r the device space bounding box
     
*
                     
of the graphics primitive being rendered.
     
* @param r2d the user space bounding box
     
*
                   
of the graphics primitive being rendered.
     
* @param xform the {@link AffineTransform} from user
     
*
              
space into device space.
     
* @param hints the set of hints that the context object can use to
     
*
              
choose between rendering alternatives.
     
* @return the {@code PaintContext} for
     
*
         
generating color patterns.
     
* @see Paint
     
* @see PaintContext
     
* @see ColorModel
     
* @see Rectangle
     
* @see Rectangle2D
     
* @see AffineTransform
     
* @see RenderingHints
     
*/

    
public synchronized PaintContext createContext(ColorModel cm, Rectangle r,
                                                   
Rectangle2D r2d,
                                                   
AffineTransform xform,
                                                   
RenderingHints hints) {
        
return new ColorPaintContext(getRGB(), cm);
    
}

    
/**
     
* Returns the transparency mode for this <code>Color</code>.
  
This is
     
* required to implement the <code>Paint</code> interface.
     
* @return this <code>Color</code> object's transparency mode.
     
* @see Paint
     
* @see Transparency
     
* @see #createContext
     
*/

    
public int getTransparency() {
        
int alpha = getAlpha();
        
if (alpha == 0xff) {
            
return Transparency.OPAQUE;
        
}
        
else if (alpha == 0) {
            
return Transparency.BITMASK;
        
}
        
else {
            
return Transparency.TRANSLUCENT;
        
}
    
}

}