// ********************************************************************** // // <copyright> // // BBN Technologies // 10 Moulton Street // Cambridge, MA 02138 // (617) 873-8000 // // Copyright (C) BBNT Solutions LLC. All rights reserved. // // </copyright> // ********************************************************************** // // $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/util/ColorFactory.java,v $ // $RCSfile: ColorFactory.java,v $ // $Revision: 1.7 $ // $Date: 2005/08/11 20:39:15 $ // $Author: dietrick $ // // ********************************************************************** package com.bbn.openmap.util; import java.awt.Color; import java.awt.Paint; import java.lang.reflect.Field; import java.util.Properties; /** * ColorFactory creates instances of colors. This class has methods which create * <code>java.awt.Color</code> or * <code>com.bbn.openmap.omGraphics.OMColor</code> objects. This class handles * creation of Color objects in a Java version-neutral way by using reflection * to create the java.awt.Color object. This way we support the extended Java 2 * platform without sacrificing support for JDK 1.1.X. * <p> * NOTE: For general RGB-colored graphics, you should directly use the * java.awt.Color 1.1.X constructors. If you are interested in using * alpha-valued colors, or using colors in a (JDK) version-neutral way, then * read on... * <p> * You may want to use this class because: * <ul> * <li>You want to use alpha-valued colors in your images under both JDK 1.1 and * JDK 1.2. (JDK1.1 has limited support for alpha-valued images). You can use * the appropriate <code>createColor()</code> methods in this class with the * <code>forceAlpha</code> set to <code>true</code> and you are guaranteed * (almost!) to get back an alpha-valued color. * <p> * <li>You want to use alpha-valued colors for generic graphics, but only in a * version-neutral way and if the support is available (e.g., you're running * under the Java 2 platform). In this case you can call the appropriate * <code>createColor()</code> methods without the <code>forceAlpha</code> * argument, or with <code>forceAlpha</code> set to false. * </ul> * * @see com.bbn.openmap.omGraphics.OMColor */ public class ColorFactory { /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p * properties * @param propName * the name of the property * @param dfault * color to use if the property value doesn't work * @return java.awt.Color * @exception NumberFormatException * if the specified string cannot be interpreted as a * hexidecimal integer * @see #parseColor(String, boolean) */ public static Color parseColorFromProperties(Properties p, String propName, String dfault) throws NumberFormatException { String colorString = p.getProperty(propName, dfault); return parseColor(colorString, true); } /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p * properties * @param propName * the name of the property * @param dfault * color to use if the property value doesn't work * @param forceAlpha * force using alpha value * @return java.awt.Color * @exception NumberFormatException * if the specified string cannot be interpreted as a * hexidecimal integer * @see #parseColor(String, boolean) */ public static Color parseColorFromProperties(Properties p, String propName, String dfault, boolean forceAlpha) throws NumberFormatException { String colorString = p.getProperty(propName, dfault); return parseColor(colorString, forceAlpha); } /** * Take a string from a properties file, representing the 24bit RGB or 32bit * ARGB hex values for a color, and convert it to a java.awt.Color. * * @param p * properties * @param propName * the name of the property * @param dfault * color to use if the property value doesn't work * @return java.awt.Color * @see #parseColor(String, boolean) */ public static Paint parseColorFromProperties(Properties p, String propName, Paint dfault) { try { String colorString = p.getProperty(propName); if (colorString != null) { return parseColor(colorString, true); } } catch (NumberFormatException nfe) { } return dfault; } /** * Convert a string representing a 24/32bit hex color value into a Color * value. * * @param colorString * the 24/32bit hex string value (ARGB) * @return java.awt.Color 24bit RGB, 24/32bit ARGB * @exception NumberFormatException * if the specified string cannot be interpreted as a * hexidecimal integer * @see #parseColor(String, boolean) */ public static Color parseColor(String colorString) throws NumberFormatException { return parseColor(colorString, true); } /** * Convert a string representing a 24/32bit hex color value into a Color * value. NOTE: * <ul> * <li>Only 24bit (RGB) java.awt.Color is supported on the JDK 1.1 platform. * <li>Both 24/32bit (ARGB) java.awt.Color is supported on the Java 2 * platform. * </ul> * * @param colorString * the 24/32bit hex string value (ARGB) * @param forceAlpha * force using alpha value * @return java.awt.Color (24bit RGB on JDK 1.1, 24/32bit ARGB on JDK1.2) * @exception NumberFormatException * if the specified string cannot be interpreted as a * hexidecimal integer * @see #createColor(int, boolean) */ public static Color parseColor(String colorString, boolean forceAlpha) throws NumberFormatException { int value; // If we come across people who do one letter per color. if (colorString.length() == 3) { colorString = new StringBuilder().append(colorString.charAt(0)).append(colorString.charAt(0)) .append(colorString.charAt(1)).append(colorString.charAt(1)).append(colorString.charAt(2)) .append(colorString.charAt(2)).toString(); } try { value = (int) Long.parseLong(colorString, 16); } catch (NumberFormatException nfe) { value = Long.decode(colorString).intValue(); // If decode can't catch it, throw an Exception... } // We want to test for this - if the length of the colorString // is less than 7, then the caller probably doesn't care about // transparency and wants the color to be opaque. However, // "0" is a common number for clear, and should be // transparent. if (colorString.length() < 7 && !colorString.equals("0")) { // Just a RGB value, use regular JDK1.1 constructor return new Color(value); } return createColor(value, forceAlpha); } /** * Create a Color. * * @param red * red component (0.0-1.0) * @param green * green component (0.0-1.0) * @param blue * blue component (0.0-1.0) * @param alpha * alpha component (0.0-1.0) * @return Color or OMColor that has an ARGB value * @see #createColor(int, boolean) */ public static Color createColor(float red, float green, float blue, float alpha) { return createColor(red, green, blue, alpha, true); } /** * Create a Color. * * @param red * red component (0.0-1.0) * @param green * green component (0.0-1.0) * @param blue * blue component (0.0-1.0) * @param alpha * alpha component (0.0-1.0) * @param forceAlpha * force using alpha value * @return Color or OMColor that has an ARGB value * @see #createColor(int, boolean) */ public static Color createColor(float red, float green, float blue, float alpha, boolean forceAlpha) { int value = (((int) (alpha * 255) & 0xff) << 24) | (((int) (red * 255) & 0xff) << 16) | (((int) (green * 255) & 0xff) << 8) | (int) (blue * 255) & 0xff; return createColor(value, forceAlpha); } /** * Create a Color. * * @param red * red component (0-255) * @param green * green component (0-255) * @param blue * blue component (0-255) * @param alpha * alpha component (0-255) * @return Color or OMColor that has an ARGB value * @see #createColor(int, boolean) */ public static Color createColor(int red, int green, int blue, int alpha) { return createColor(red, green, blue, alpha, true); } /** * Create a Color. * * @param red * red component (0-255) * @param green * green component (0-255) * @param blue * blue component (0-255) * @param alpha * alpha component (0-255) * @param forceAlpha * force using alpha value * @return Color or OMColor that has an ARGB value * @see #createColor(int, boolean) */ public static Color createColor(int red, int green, int blue, int alpha, boolean forceAlpha) { int value = ((alpha & 0xff) << 24) | ((red & 0xff) << 16) | ((green & 0xff) << 8) | blue & 0xff; return createColor(value, forceAlpha); } /** * Create a Color. * * @param value * 32bit ARGB color value * @return Color or OMColor that has an ARGB value * @see #createColor(int, boolean) */ public static Color createColor(int value) { return createColor(value, true); } /** * Create a Color. * * @param value * 32bit ARGB color value * @param forceAlpha * force using alpha value the underlying java.awt.Color supports * it * @return Color or OMColor that has an ARGB value */ public static Color createColor(int value, boolean forceAlpha) { return new Color(value, forceAlpha); } public static String getHexColorString(Color color) { return Integer.toHexString((color.getRGB() & 0x00FFFFFF) | (color.getAlpha() << 24)); } /** * Method that returns a java.awt.Color object given the name of the color. * Depends on the static instances of color provided by the java.awt.Color * class. * * @param name * @param defaultColor * @return Color that reflects the name, or the default color. */ public static Color getNamedColor(String name, Color defaultColor) { if (name != null) { Field[] colorFields = Color.class.getDeclaredFields(); for (int i = 0; i < colorFields.length; i++) { Field f = colorFields[i]; try { if (name.equalsIgnoreCase(f.getName())) { return (Color) f.get((Object) null); } } catch (IllegalAccessException iae) { // Whoa, shouldn't happen, but hey } catch (ClassCastException cce) { // Shouldn't ask for anything other than colors, // either. } } } return defaultColor; } }