001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-present, by David Gilbert and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * ---------------
028 * PaintUtils.java
029 * ---------------
030 * (C) Copyright 2000-present, by David Gilbert and Contributors.
031 *
032 * Original Author:  David Gilbert;
033 * Contributors:     -;
034 */
035
036package org.jfree.chart.util;
037
038import java.awt.Color;
039import java.awt.GradientPaint;
040import java.awt.LinearGradientPaint;
041import java.awt.Paint;
042import java.awt.RadialGradientPaint;
043import java.lang.reflect.Field;
044import java.lang.reflect.Modifier;
045import java.util.Arrays;
046
047/**
048 * Utility code that relates to {@code Paint} objects.
049 */
050public class PaintUtils {
051
052    /**
053     * Private constructor prevents object creation.
054     */
055    private PaintUtils() {
056    }
057
058    /**
059     * Returns {@code true} if the two {@code Paint} objects are equal 
060     * OR both {@code null}.  This method handles
061     * {@code GradientPaint}, {@code LinearGradientPaint} and 
062     * {@code RadialGradientPaint} as a special cases, since those classes do
063     * not override the {@code equals()} method.
064     *
065     * @param p1  paint 1 ({@code null} permitted).
066     * @param p2  paint 2 ({@code null} permitted).
067     *
068     * @return A boolean.
069     */
070    public static boolean equal(Paint p1, Paint p2) {
071        if (p1 == p2) {
072            return true;
073        }
074            
075        // handle cases where either or both arguments are null
076        if (p1 == null) {
077            return (p2 == null);   
078        }
079        if (p2 == null) {
080            return false;   
081        }
082
083        // handle GradientPaint as a special case...
084        if (p1 instanceof GradientPaint && p2 instanceof GradientPaint) {
085            GradientPaint gp1 = (GradientPaint) p1;
086            GradientPaint gp2 = (GradientPaint) p2;
087            return gp1.getColor1().equals(gp2.getColor1()) 
088                    && gp1.getColor2().equals(gp2.getColor2())
089                    && gp1.getPoint1().equals(gp2.getPoint1())    
090                    && gp1.getPoint2().equals(gp2.getPoint2())
091                    && gp1.isCyclic() == gp2.isCyclic()
092                    && gp1.getTransparency() == gp1.getTransparency(); 
093        } else if (p1 instanceof LinearGradientPaint 
094                && p2 instanceof LinearGradientPaint) {
095            LinearGradientPaint lgp1 = (LinearGradientPaint) p1;
096            LinearGradientPaint lgp2 = (LinearGradientPaint) p2;
097            return lgp1.getStartPoint().equals(lgp2.getStartPoint())
098                    && lgp1.getEndPoint().equals(lgp2.getEndPoint()) 
099                    && Arrays.equals(lgp1.getFractions(), lgp2.getFractions())
100                    && Arrays.equals(lgp1.getColors(), lgp2.getColors())
101                    && lgp1.getCycleMethod() == lgp2.getCycleMethod()
102                    && lgp1.getColorSpace() == lgp2.getColorSpace()
103                    && lgp1.getTransform().equals(lgp2.getTransform());
104        } else if (p1 instanceof RadialGradientPaint 
105                && p2 instanceof RadialGradientPaint) {
106            RadialGradientPaint rgp1 = (RadialGradientPaint) p1;
107            RadialGradientPaint rgp2 = (RadialGradientPaint) p2;
108            return rgp1.getCenterPoint().equals(rgp2.getCenterPoint())
109                    && rgp1.getRadius() == rgp2.getRadius() 
110                    && rgp1.getFocusPoint().equals(rgp2.getFocusPoint())
111                    && Arrays.equals(rgp1.getFractions(), rgp2.getFractions())
112                    && Arrays.equals(rgp1.getColors(), rgp2.getColors())
113                    && rgp1.getCycleMethod() == rgp2.getCycleMethod()
114                    && rgp1.getColorSpace() == rgp2.getColorSpace()
115                    && rgp1.getTransform().equals(rgp2.getTransform());
116        } else {
117            return p1.equals(p2);
118        }
119    }
120
121    /**
122     * Converts a color into a string. If the color is equal to one of the
123     * defined constant colors, that name is returned instead. Otherwise the
124     * color is returned as hex-string.
125     *
126     * @param c the color.
127     * @return the string for this color.
128     */
129    public static String colorToString(Color c) {
130        try {
131            Field[] fields = Color.class.getFields();
132            for (int i = 0; i < fields.length; i++) {
133                Field f = fields[i];
134                if (Modifier.isPublic(f.getModifiers())
135                        && Modifier.isFinal(f.getModifiers())
136                        && Modifier.isStatic(f.getModifiers())) {
137                    final String name = f.getName();
138                    final Object oColor = f.get(null);
139                    if (oColor instanceof Color) {
140                        if (c.equals(oColor)) {
141                            return name;
142                        }
143                    }
144                }
145            }
146        } catch (Exception e) {
147            //
148        }
149
150        // no defined constant color, so this must be a user defined color
151        final String color = Integer.toHexString(c.getRGB() & 0x00ffffff);
152        final StringBuilder retval = new StringBuilder(7);
153        retval.append("#");
154
155        final int fillUp = 6 - color.length();
156        for (int i = 0; i < fillUp; i++) {
157            retval.append("0");
158        }
159
160        retval.append(color);
161        return retval.toString();
162    }
163
164    /**
165     * Converts a given string into a color.
166     *
167     * @param value the string, either a name or a hex-string.
168     * @return the color.
169     */
170    public static Color stringToColor(String value) {
171        if (value == null) {
172            return Color.BLACK;
173        }
174        try {
175            // get color by hex or octal value
176            return Color.decode(value);
177        } catch (NumberFormatException nfe) {
178            // if we can't decode lets try to get it by name
179            try {
180                // try to get a color by name using reflection
181                final Field f = Color.class.getField(value);
182                return (Color) f.get(null);
183            } catch (Exception ce) {
184                // if we can't get any color return black
185                return Color.BLACK;
186            }
187        }
188    }
189}
190