- /*
- * @(#)Color.java 1.66 00/02/02
- *
- * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the proprietary information of Sun Microsystems, Inc.
- * Use is subject to license terms.
- *
- */
-
- package java.awt;
-
- import java.io.*;
- import java.lang.*;
- 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 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 light gray. In the default sRGB space.
- */
- public final static Color lightGray = new Color(192, 192, 192);
-
- /**
- * The color gray. In the default sRGB space.
- */
- public final static Color gray = new Color(128, 128, 128);
-
- /**
- * The color dark gray. In the default sRGB space.
- */
- public final static Color darkGray = new Color(64, 64, 64);
-
- /**
- * The color black. In the default sRGB space.
- */
- public final static Color black = new Color(0, 0, 0);
-
- /**
- * The color red. In the default sRGB space.
- */
- public final static Color red = new Color(255, 0, 0);
-
- /**
- * The color pink. In the default sRGB space.
- */
- public final static Color pink = new Color(255, 175, 175);
-
- /**
- * The color orange. In the default sRGB space.
- */
- public final static Color orange = new Color(255, 200, 0);
-
- /**
- * The color yellow. In the default sRGB space.
- */
- public final static Color yellow = new Color(255, 255, 0);
-
- /**
- * The color green. In the default sRGB space.
- */
- public final static Color green = new Color(0, 255, 0);
-
- /**
- * The color magenta. In the default sRGB space.
- */
- public final static Color magenta = new Color(255, 0, 255);
-
- /**
- * The color cyan. In the default sRGB space.
- */
- public final static Color cyan = new Color(0, 255, 255);
-
- /**
- * The color blue. In the default sRGB space.
- */
- public final static Color blue = new Color(0, 0, 255);
-
- /**
- * Private data.
- */
- transient private long pData;
-
- /**
- * 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();
- 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.
- * @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).
- * @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(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.
- * @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.
- * @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
- * @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>. 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>.
- * @see java.awt.Color#darker
- * @since JDK1.0
- */
- public Color brighter() {
- int r = getRed();
- int g = getGreen();
- int b = getBlue();
-
- /* 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);
- }
- 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)(rFACTOR), 255),
- Math.min((int)(gFACTOR), 255),
- Math.min((int)(bFACTOR), 255));
- }
-
- /**
- * 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>. 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>.
- * @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));
- }
-
- /**
- * 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, and blue 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).value == this.value;
- }
-
- /**
- * 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 hexidecimal 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 hexidecimal 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() <code>getRGB</code>}.
- * 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;
- }
-
- // REMIND: this should really be a Ref!
- /**
- * The paint context used to generate a solid color pattern.
- * @serial
- * @see createContext()
- */
- private PaintContext theContext;
-
- /**
- * Creates and returns a {@link PaintContext} used to generate a solid
- * color pattern. This enables a <code>Color</code> object to be used
- * as an argument to any method requiring an object implementing the
- * {@link Paint} interface.
- * The same <code>PaintContext</code> is returned, regardless of
- * whether or not <code>r</code>, <code>r2d</code>,
- * <code>xform</code>, or <code>hints</code> are <code>null</code>.
- * @param cm the specified <code>ColorModel</code>
- * @param r the specified {@link Rectangle}
- * @param r2d the specified {@link Rectangle2D}
- * @param xform the specified {@link AffineTransform}
- * @param hints the specified {@link RenderingHints}
- * @return a <code>PaintContext</code> that is used to generate a
- * solid color pattern.
- * @see Paint
- * @see PaintContext
- * @see Graphics2D#setPaint
- */
- public synchronized PaintContext createContext(ColorModel cm, Rectangle r,
- Rectangle2D r2d,
- AffineTransform xform,
- RenderingHints hints) {
- PaintContext pc = theContext;
- if (pc == null) {
- pc = new ColorPaintContext(value, cm);
- theContext = pc;
- }
- return pc;
- }
-
- /**
- * 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;
- }
- }
-
- }