home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / Color.java < prev    next >
Text File  |  1998-09-22  |  22KB  |  613 lines

  1. /*
  2.  * @(#)Color.java    1.34 98/07/01
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  * 
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.io.*;
  17. import java.lang.*;
  18.  
  19. /**
  20.  * This class encapsulates colors using the RGB format. In RGB 
  21.  * format, the red, blue, and green components of a color are each 
  22.  * represented by an integer in the range 0-255. The value 0 
  23.  * indicates no contribution from this primary color. The value 255 
  24.  * indicates the maximum intensity of this color component. 
  25.  * <p>
  26.  * Although the <code>Color</code> class is based on the 
  27.  * three-component RGB model, the class provides a set of convenience 
  28.  * methods for converting between RGB and HSB colors. For a 
  29.  * definition of the RGB and HSB color models, see Foley, van Dam, 
  30.  * Feiner, and Hughes, <cite>Computer Graphics: Principles 
  31.  * and Practice</cite>.
  32.  *
  33.  * @version     1.34, 07/01/98
  34.  * @author     Sami Shaio
  35.  * @author     Arthur van Hoff
  36.  * @since       JDK1.0
  37.  */
  38. public class Color implements java.io.Serializable {
  39.     
  40.     /**
  41.      * The color white.
  42.      */
  43.     public final static Color white     = new Color(255, 255, 255);
  44.  
  45.     /**
  46.      * The color light gray.
  47.      */
  48.     public final static Color lightGray = new Color(192, 192, 192);
  49.  
  50.     /**
  51.      * The color gray.
  52.      */
  53.     public final static Color gray     = new Color(128, 128, 128);
  54.  
  55.     /**
  56.      * The color dark gray.
  57.      */
  58.     public final static Color darkGray     = new Color(64, 64, 64);
  59.  
  60.     /**
  61.      * The color black.
  62.      */
  63.     public final static Color black     = new Color(0, 0, 0);
  64.     
  65.     /**
  66.      * The color red.
  67.      */
  68.     public final static Color red     = new Color(255, 0, 0);
  69.  
  70.     /**
  71.      * The color pink.
  72.      */
  73.     public final static Color pink     = new Color(255, 175, 175);
  74.  
  75.     /**
  76.      * The color orange.
  77.      */
  78.     public final static Color orange     = new Color(255, 200, 0);
  79.  
  80.     /**
  81.      * The color yellow.
  82.      */
  83.     public final static Color yellow     = new Color(255, 255, 0);
  84.  
  85.     /**
  86.      * The color green.
  87.      */
  88.     public final static Color green     = new Color(0, 255, 0);
  89.  
  90.     /**
  91.      * The color magenta.
  92.      */
  93.     public final static Color magenta    = new Color(255, 0, 255);
  94.  
  95.     /**
  96.      * The color cyan.
  97.      */
  98.     public final static Color cyan     = new Color(0, 255, 255);
  99.  
  100.     /**
  101.      * The color blue.
  102.      */
  103.     public final static Color blue     = new Color(0, 0, 255);
  104.  
  105.     /**
  106.      * Private data.
  107.      */
  108.     transient private int pData;
  109.  
  110.     /**
  111.      * The color value.
  112.      */
  113.     int value;
  114.  
  115.     /*
  116.      * JDK 1.1 serialVersionUID 
  117.      */
  118.      private static final long serialVersionUID = 118526816881161077L;
  119.  
  120.     /**
  121.      * Checks the color integer components supplied for validity.
  122.      * Throws an IllegalArgumentException if the value is out of range.
  123.      * @param r the Red component
  124.      * @param g the Green component
  125.      * @param b the Blue component
  126.      **/
  127.     private static void testColorValueRange(int r, int g, int b) {
  128.         boolean rangeError = false;
  129.     String badComponentString = "";
  130.     if ( r < 0 || r > 255) {
  131.         rangeError = true;
  132.         badComponentString = badComponentString + " Red";
  133.     }
  134.     if ( g < 0 || g > 255) {
  135.         rangeError = true;
  136.         badComponentString = badComponentString + " Green";
  137.     }
  138.     if ( b < 0 || b > 255) {
  139.         rangeError = true;
  140.         badComponentString = badComponentString + " Blue";
  141.     }
  142.     if ( rangeError == true ) {
  143.     throw new IllegalArgumentException("Color parameter outside of expected range:"
  144.                        + badComponentString);
  145.     }
  146.     }
  147.  
  148.     /**
  149.      * Checks the color float components supplied for validity.
  150.      * Throws an IllegalArgumentException if the value is out of range.
  151.      * @param r the Red component
  152.      * @param g the Green component
  153.      * @param b the Blue component
  154.      **/
  155.     private static void testColorValueRange(float r, float g, float b) {
  156.         boolean rangeError = false;
  157.     String badComponentString = "";
  158.     if ( r < 0.0 || r > 1.0) {
  159.         rangeError = true;
  160.         badComponentString = badComponentString + " Red";
  161.     }
  162.     if ( g < 0.0 || g > 1.0) {
  163.         rangeError = true;
  164.         badComponentString = badComponentString + " Green";
  165.     }
  166.     if ( b < 0.0 || b > 1.0) {
  167.         rangeError = true;
  168.         badComponentString = badComponentString + " Blue";
  169.     }
  170.     if ( rangeError == true ) {
  171.     throw new IllegalArgumentException("Color parameter outside of expected range:"
  172.                        + badComponentString);
  173.     }
  174.     }
  175.  
  176.     /**
  177.      * Creates a color with the specified red, green, and blue 
  178.      * components. The three arguments must each be in the range 
  179.      * 0-255. 
  180.      * <p>
  181.      * The actual color used in rendering depends on finding the best 
  182.      * match given the color space available for a given output device. 
  183.      * @param       r the red component.
  184.      * @param       g the green component.
  185.      * @param       b the blue component.
  186.      * @see         java.awt.Color#getRed.
  187.      * @see         java.awt.Color#getGreen.
  188.      * @see         java.awt.Color#getBlue.
  189.      * @see         java.awt.Color#getRGB.
  190.      * @since       JDK1.0
  191.      */
  192.     public Color(int r, int g, int b) {
  193.         this(((r & 0xFF) << 16) | ((g & 0xFF) << 8) | ((b & 0xFF) << 0));
  194.     testColorValueRange(r,g,b);
  195.     }
  196.  
  197.     /**
  198.      * Creates a color with the specified RGB value, where the red 
  199.      * component is in bits 16-23 of the argument, the green 
  200.      * component is in bits 8-15 of the argument, and the blue 
  201.      * component is in bits 0-7. The value zero indicates no 
  202.      * contribution from the primary color component. 
  203.      * <p>
  204.      * The actual color used in rendering depends on finding the best 
  205.      * match given the color space available for a given output device. 
  206.      * @param       rgb   an integer giving the red, green, and blue components.
  207.      * @see         java.awt.image.ColorModel#getRGBdefault
  208.      * @see         java.awt.Color#getRed.
  209.      * @see         java.awt.Color#getGreen.
  210.      * @see         java.awt.Color#getBlue.
  211.      * @see         java.awt.Color#getRGB.
  212.      * @since       JDK1.0
  213.      */
  214.     public Color(int rgb) {
  215.       value = 0xff000000 | rgb;
  216.     }
  217.  
  218.     /**
  219.      * Creates a color with the specified red, green, and blue values, 
  220.      * where each of the values is in the range 0.0-1.0. The value 
  221.      * 0.0 indicates no contribution from the primary color component. 
  222.      * The value 1.0 indicates the maximum intensity of the primary color 
  223.      * component. 
  224.      * <p>
  225.      * The actual color used in rendering depends on finding the best 
  226.      * match given the color space available for a given output device. 
  227.      * @param       r the red component
  228.      * @param       g the red component
  229.      * @param       b the red component
  230.      * @see         java.awt.Color#getRed.
  231.      * @see         java.awt.Color#getGreen.
  232.      * @see         java.awt.Color#getBlue.
  233.      * @see         java.awt.Color#getRGB.
  234.      * @since       JDK1.0
  235.      */
  236.     public Color(float r, float g, float b) {
  237.       this( (int) (r * 255), (int) (g * 255), (int) (b * 255));
  238.       testColorValueRange(r,g,b);
  239.     }
  240.  
  241.     /**
  242.      * Gets the red component of this color. The result is 
  243.      * an integer in the range 0 to 255. 
  244.      * @return        the red component of this color.
  245.      * @see           java.awt.Color#getRGB
  246.      * @since         JDK1.0
  247.      */
  248.     public int getRed() {
  249.     return (getRGB() >> 16) & 0xFF;
  250.     }
  251.  
  252.     /**
  253.      * Gets the green component of this color. The result is 
  254.      * an integer in the range 0 to 255. 
  255.      * @return        the green component of this color.
  256.      * @see           java.awt.Color#getRGB
  257.      * @since         JDK1.0
  258.      */
  259.     public int getGreen() {
  260.     return (getRGB() >> 8) & 0xFF;
  261.     }
  262.  
  263.     /**
  264.      * Gets the blue component of this color. The result is 
  265.      * an integer in the range 0 to 255. 
  266.      * @return        the blue component of this color.
  267.      * @see           java.awt.Color#getRGB
  268.      * @since         JDK1.0
  269.      */
  270.     public int getBlue() {
  271.     return (getRGB() >> 0) & 0xFF;
  272.     }
  273.  
  274.     /**
  275.      * Gets the RGB value representing the color in the default RGB ColorModel. 
  276.      * The red, green, and blue components of the color are each scaled to be 
  277.      * a value between 0 (abscence of the color) and 255 (complete saturation). 
  278.      * Bits 24-31 of the returned integer are 0xff, bits 16-23 are the red 
  279.      * value, bit 8-15 are the green value, and bits 0-7 are the blue value.
  280.      * @see java.awt.image.ColorModel#getRGBdefault
  281.      * @see #getRed
  282.      * @see #getGreen
  283.      * @see #getBlue
  284.      * @since JDK1.0
  285.      */
  286.     public int getRGB() {
  287.     return value;
  288.     }
  289.  
  290.     private static final double FACTOR = 0.7;
  291.  
  292.     /**
  293.      * Creates a brighter version of this color.
  294.      * <p>
  295.      * This method applies an arbitrary scale factor to each of the three RGB 
  296.      * components of the color to create a brighter version of the same 
  297.      * color. Although <code>brighter</code> and <code>darker</code> are 
  298.      * inverse operations, the results of a series of invocations of 
  299.      * these two methods may be inconsistent because of rounding errors. 
  300.      * @return     a new <code>Color</code> object, 
  301.      *                            a brighter version of this color.
  302.      * @see        java.awt.Color#darker
  303.      * @since      JDK1.0
  304.      */
  305.     public Color brighter() {
  306.     int r = getRed();
  307.     int g = getGreen();
  308.     int b = getBlue();
  309.  
  310.     /* From 2D group:
  311.          * 1. black.brighter() should return grey
  312.      * 2. applying brighter to blue will always return blue, brighter
  313.          * 3. non pure color (non zero rgb) will eventually return white
  314.          */
  315.     int i = (int)(1.0/(1.0-FACTOR));
  316.     if ( r == 0 && g == 0 && b == 0) {
  317.        return new Color(i, i, i);
  318.         }
  319.     if ( r > 0 && r < i ) r = i;
  320.     if ( g > 0 && g < i ) g = i;
  321.     if ( b > 0 && b < i ) b = i;
  322.  
  323.     return new Color(Math.min((int)(r/FACTOR), 255), 
  324.              Math.min((int)(g/FACTOR), 255),
  325.              Math.min((int)(b/FACTOR), 255));
  326.     }
  327.  
  328.     /**
  329.      * Creates a darker version of this color.
  330.      * <p>
  331.      * This method applies an arbitrary scale factor to each of the three RGB 
  332.      * components of the color to create a darker version of the same 
  333.      * color. Although <code>brighter</code> and <code>darker</code> are 
  334.      * inverse operations, the results of a series of invocations of 
  335.      * these two methods may be inconsistent because of rounding errors. 
  336.      * @return  a new <code>Color</code> object, 
  337.      *                              a darker version of this color.
  338.      * @see        java.awt.Color#brighter
  339.      * @since      JDK1.0
  340.      */
  341.     public Color darker() {
  342.     return new Color(Math.max((int)(getRed()  *FACTOR), 0), 
  343.              Math.max((int)(getGreen()*FACTOR), 0),
  344.              Math.max((int)(getBlue() *FACTOR), 0));
  345.     }
  346.  
  347.     /**
  348.      * Computes the hash code for this color.
  349.      * @return     a hash code value for this object.
  350.      * @since      JDK1.0
  351.      */
  352.     public int hashCode() {
  353.     return value;
  354.     }
  355.  
  356.     /**
  357.      * Determines whether another object is equal to this color.
  358.      * <p>
  359.      * The result is <code>true</code> if and only if the argument is not 
  360.      * <code>null</code> and is a <code>Color</code> object that has the same 
  361.      * red, green, and blue values as this object. 
  362.      * @param       obj   the object to compare with.
  363.      * @return      <code>true</code> if the objects are the same; 
  364.      *                             <code>false</code> otherwise.
  365.      * @since   JDK1.0
  366.      */
  367.     public boolean equals(Object obj) {
  368.         return obj instanceof Color && ((Color)obj).value == this.value;
  369.     }
  370.  
  371.     /**
  372.      * Creates a string that represents this color and indicates the 
  373.      * values of its RGB components. 
  374.      * @return     a representation of this color as a 
  375.      *                           <code>String</code> object.
  376.      * @since      JDK1.0
  377.      */
  378.     public String toString() {
  379.         return getClass().getName() + "[r=" + getRed() + ",g=" + getGreen() + ",b=" + getBlue() + "]";
  380.     }
  381.  
  382.     /**
  383.      * Converts a string to an integer and returns the 
  384.      * specified color. This method handles string formats that 
  385.      * are used to represent octal and hexidecimal numbers.
  386.      * @param      nm a string that represents 
  387.      *                            a color as a 24-bit integer.
  388.      * @return     the new color
  389.      * @see        java.lang.Integer#decode
  390.      * @exception  NumberFormatException  if the specified string cannot
  391.      *                      be interpreted as a decimal, 
  392.      *                      octal, or hexidecimal integer.
  393.      * @since      JDK1.1
  394.      */
  395.     public static Color decode(String nm) throws NumberFormatException {
  396.     Integer intval = Integer.decode(nm);
  397.     int i = intval.intValue();
  398.     return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  399.     }
  400.  
  401.     /**
  402.      * Finds a color in the system properties. 
  403.      * <p>
  404.      * The argument is treated as the name of a system property to 
  405.      * be obtained. The string value of this property is then interpreted 
  406.      * as an integer which is then converted to a color. 
  407.      * <p>
  408.      * If the specified property is not found, or could not be parsed as 
  409.      * an integer, then <code>null</code> is returned. 
  410.      * @param    nm the name of the color property
  411.      * @return   the color value of the property.
  412.      * @see      java.lang.System#getProperty(java.lang.String)
  413.      * @see      java.lang.Integer#getInteger(java.lang.String)
  414.      * @see      java.awt.Color#Color(int)
  415.      * @since    JDK1.0
  416.      */
  417.     public static Color getColor(String nm) {
  418.     return getColor(nm, null);
  419.     }
  420.  
  421.     /**
  422.      * Finds a color in the system properties. 
  423.      * <p>
  424.      * The first argument is treated as the name of a system property to 
  425.      * be obtained. The string value of this property is then interpreted 
  426.      * as an integer which is then converted to a color. 
  427.      * <p>
  428.      * If the specified property is not found, or cannot be parsed as 
  429.      * an integer, then the color specified by the second argument is 
  430.      * returned instead. 
  431.      * @param    nm the name of the color property
  432.      * @param    v    the default color value.
  433.      * @return   the color value of the property.
  434.      * @see      java.lang.System#getProperty(java.lang.String)
  435.      * @see      java.lang.Integer#getInteger(java.lang.String)
  436.      * @see      java.awt.Color#Color(int)
  437.      * @since    JDK1.0
  438.      */
  439.     public static Color getColor(String nm, Color v) {
  440.     Integer intval = Integer.getInteger(nm);
  441.     if (intval == null) {
  442.         return v;
  443.     }
  444.     int i = intval.intValue();
  445.     return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
  446.     }
  447.  
  448.     /**
  449.      * Finds a color in the system properties. 
  450.      * <p>
  451.      * The first argument is treated as the name of a system property to 
  452.      * be obtained. The string value of this property is then interpreted 
  453.      * as an integer which is then converted to a color. 
  454.      * <p>
  455.      * If the specified property is not found, or could not be parsed as 
  456.      * an integer, then the integer value <code>v</code> is used instead, 
  457.      * and is converted to a color.
  458.      * @param    nm  the name of the color property.
  459.      * @param    v   the default color value, as an integer.
  460.      * @return   the color value of the property.
  461.      * @see      java.lang.System#getProperty(java.lang.String)
  462.      * @see      java.lang.Integer#getInteger(java.lang.String)
  463.      * @see      java.awt.Color#Color(int)
  464.      * @since    JDK1.0
  465.      */
  466.     public static Color getColor(String nm, int v) {
  467.     Integer intval = Integer.getInteger(nm);
  468.     int i = (intval != null) ? intval.intValue() : v;
  469.     return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, (i >> 0) & 0xFF);
  470.     }
  471.  
  472.     /**
  473.      * Converts the components of a color, as specified by the HSB 
  474.      * model, to an equivalent set of values for the RGB model. 
  475.      * <p>
  476.      * The integer that is returned by <code>HSBtoRGB</code> encodes the 
  477.      * value of a color in bits 0&endash;23 of an integer value, the same 
  478.      * format used by the method <code>getRGB</code>. This integer can be 
  479.      * supplied as an argument to the <code>Color</code> constructor that 
  480.      * takes a single integer argument. 
  481.      * @param     hue   the hue component of the color.
  482.      * @param     saturation   the saturation of the color.
  483.      * @param     brightness   the brightness of the color.
  484.      * @return    the RGB value of the color with the indicated hue, 
  485.      *                            saturation, and brightness.
  486.      * @see       java.awt.Color#getRGB()
  487.      * @see       java.awt.Color#Color(int)
  488.      * @since     JDK1.0
  489.      */
  490.     public static int HSBtoRGB(float hue, float saturation, float brightness) {
  491.     int r = 0, g = 0, b = 0;
  492.         if (saturation == 0) {
  493.         r = g = b = (int) (brightness * 255);
  494.     } else {
  495.         double h = (hue - Math.floor(hue)) * 6.0;
  496.         double f = h - java.lang.Math.floor(h);
  497.         double p = brightness * (1.0 - saturation);
  498.         double q = brightness * (1.0 - saturation * f);
  499.         double t = brightness * (1.0 - (saturation * (1.0 - f)));
  500.         switch ((int) h) {
  501.         case 0:
  502.         r = (int) (brightness * 255);
  503.         g = (int) (t * 255);
  504.         b = (int) (p * 255);
  505.         break;
  506.         case 1:
  507.         r = (int) (q * 255);
  508.         g = (int) (brightness * 255);
  509.         b = (int) (p * 255);
  510.         break;
  511.         case 2:
  512.         r = (int) (p * 255);
  513.         g = (int) (brightness * 255);
  514.         b = (int) (t * 255);
  515.         break;
  516.         case 3:
  517.         r = (int) (p * 255);
  518.         g = (int) (q * 255);
  519.         b = (int) (brightness * 255);
  520.         break;
  521.         case 4:
  522.         r = (int) (t * 255);
  523.         g = (int) (p * 255);
  524.         b = (int) (brightness * 255);
  525.         break;
  526.         case 5:
  527.         r = (int) (brightness * 255);
  528.         g = (int) (p * 255);
  529.         b = (int) (q * 255);
  530.         break;
  531.         }
  532.     }
  533.     return 0xff000000 | (r << 16) | (g << 8) | (b << 0);
  534.     }
  535.  
  536.     /**
  537.      * Converts the components of a color, as specified by the RGB 
  538.      * model, to an equivalent set of values for hue, saturation, and 
  539.      * brightness, the three components of the HSB model. 
  540.      * <p>
  541.      * If the <code>hsbvals</code> argument is <code>null</code>, then a 
  542.      * new array is allocated to return the result. Otherwise, the method 
  543.      * returns the array <code>hsbvals</code>, with the values put into 
  544.      * that array. 
  545.      * @param     r   the red component of the color.
  546.      * @param     g   the green component of the color.
  547.      * @param     b   the blue component of the color.
  548.      * @param     hsbvals  the array to be used to return the 
  549.      *                     three HSB values, or <code>null</code>.
  550.      * @return    an array of three elements containing the hue, saturation, 
  551.      *                     and brightness (in that order), of the color with 
  552.      *                     the indicated red, green, and blue components.
  553.      * @see       java.awt.Color#getRGB()
  554.      * @see       java.awt.Color#Color(int)
  555.      * @since     JDK1.0
  556.      */
  557.     public static float[] RGBtoHSB(int r, int g, int b, float[] hsbvals) {
  558.     float hue, saturation, brightness;
  559.     if (hsbvals == null) {
  560.         hsbvals = new float[3];
  561.     }
  562.         int cmax = (r > g) ? r : g;
  563.     if (b > cmax) cmax = b;
  564.     int cmin = (r < g) ? r : g;
  565.     if (b < cmin) cmin = b;
  566.  
  567.     brightness = ((float) cmax) / 255.0f;
  568.     if (cmax != 0)
  569.         saturation = ((float) (cmax - cmin)) / ((float) cmax);
  570.     else
  571.         saturation = 0;
  572.     if (saturation == 0)
  573.         hue = 0;
  574.     else {
  575.         float redc = ((float) (cmax - r)) / ((float) (cmax - cmin));
  576.         float greenc = ((float) (cmax - g)) / ((float) (cmax - cmin));
  577.         float bluec = ((float) (cmax - b)) / ((float) (cmax - cmin));
  578.         if (r == cmax)
  579.         hue = bluec - greenc;
  580.         else if (g == cmax)
  581.             hue = 2.0f + redc - bluec;
  582.             else
  583.         hue = 4.0f + greenc - redc;
  584.         hue = hue / 6.0f;
  585.         if (hue < 0)
  586.         hue = hue + 1.0f;
  587.     }
  588.     hsbvals[0] = hue;
  589.     hsbvals[1] = saturation;
  590.     hsbvals[2] = brightness;
  591.     return hsbvals;
  592.     }
  593.  
  594.     /**
  595.      * Creates a <code>Color</code> object based on values supplied 
  596.      * for the HSB color model. 
  597.      * <p>
  598.      * Each of the three components should be a floating-point 
  599.      * value between zero and one (a number in the range 
  600.      * <code>0.0</code> ≤ <code>h</code>, <code>s</code>, 
  601.      * <code>b</code> ≤ <code>1.0). </code> 
  602.      * @param  h   the hue component.
  603.      * @param  s   the saturation of the color.
  604.      * @param  b   the brightness of the color.
  605.      * @return  a <code>Color</code> object with the specified hue, 
  606.      *                                 saturation, and brightness.
  607.      * @since   JDK1.0
  608.      */
  609.     public static Color getHSBColor(float h, float s, float b) {
  610.     return new Color(HSBtoRGB(h, s, b));
  611.     }
  612. }
  613.