/*
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
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 - 1.0 or 0 - 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.
* @return a 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>.
* @return a 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
* @return the new <code>Color</code> object.
* @see java.lang.Integer#decode
* @exception NumberFormatException if 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 v the 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.
* @param hue the hue component of the color
* @param saturation the saturation of the color
* @param brightness 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()
* @since JDK1.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.
* @param r the red component of the color
* @param g the green component of the color
* @param b the blue component of the color
* @param hsbvals 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()
* @since JDK1.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;
}
}
}