001/* ========================================================================
002 * JCommon : a free general purpose class library for the Java(tm) platform
003 * ========================================================================
004 *
005 * (C) Copyright 2000-2017, by Object Refinery Limited and Contributors.
006 * 
007 * Project Info:  http://www.jfree.org/jcommon/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 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025 * in the United States and other countries.]
026 * 
027 * -------------------
028 * PaintUtilities.java
029 * -------------------
030 * (C) Copyright 2003-2016, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   -;
034 *
035 * Changes
036 * -------
037 * 13-Nov-2003 : Version 1 (DG);
038 * 04-Oct-2004 : Renamed PaintUtils --> PaintUtilities (DG);
039 * 23-Feb-2005 : Rewrote equal() method with less indenting required (DG);
040 * 16-Jan-2016 : Update equal() test (DG);
041 *
042 */
043
044package org.jfree.util;
045
046import java.awt.Color;
047import java.awt.GradientPaint;
048import java.awt.LinearGradientPaint;
049import java.awt.Paint;
050import java.awt.RadialGradientPaint;
051import java.lang.reflect.Field;
052import java.lang.reflect.Modifier;
053import java.util.Arrays;
054
055/**
056 * Utility code that relates to {@code Paint} objects.
057 */
058public class PaintUtilities {
059
060    /**
061     * Private constructor prevents object creation.
062     */
063    private PaintUtilities() {
064    }
065
066    /**
067     * Returns {@code true} if the two {@code Paint} objects are equal 
068     * OR both {@code null}.  This method handles
069     * {@code GradientPaint}, {@code LinearGradientPaint} and 
070     * {@code RadialGradientPaint} as a special cases, since those classes do
071     * not override the {@code equals()} method.
072     *
073     * @param p1  paint 1 ({@code null} permitted).
074     * @param p2  paint 2 ({@code null} permitted).
075     *
076     * @return A boolean.
077     */
078    public static boolean equal(Paint p1, Paint p2) {
079        if (p1 == p2) {
080            return true;
081        }
082            
083        // handle cases where either or both arguments are null
084        if (p1 == null) {
085            return (p2 == null);   
086        }
087        if (p2 == null) {
088            return false;   
089        }
090
091        // handle GradientPaint as a special case...
092        if (p1 instanceof GradientPaint && p2 instanceof GradientPaint) {
093            GradientPaint gp1 = (GradientPaint) p1;
094            GradientPaint gp2 = (GradientPaint) p2;
095            return gp1.getColor1().equals(gp2.getColor1()) 
096                    && gp1.getColor2().equals(gp2.getColor2())
097                    && gp1.getPoint1().equals(gp2.getPoint1())    
098                    && gp1.getPoint2().equals(gp2.getPoint2())
099                    && gp1.isCyclic() == gp2.isCyclic()
100                    && gp1.getTransparency() == gp1.getTransparency(); 
101        } else if (p1 instanceof LinearGradientPaint 
102                && p2 instanceof LinearGradientPaint) {
103            LinearGradientPaint lgp1 = (LinearGradientPaint) p1;
104            LinearGradientPaint lgp2 = (LinearGradientPaint) p2;
105            return lgp1.getStartPoint().equals(lgp2.getStartPoint())
106                    && lgp1.getEndPoint().equals(lgp2.getEndPoint()) 
107                    && Arrays.equals(lgp1.getFractions(), lgp2.getFractions())
108                    && Arrays.equals(lgp1.getColors(), lgp2.getColors())
109                    && lgp1.getCycleMethod() == lgp2.getCycleMethod()
110                    && lgp1.getColorSpace() == lgp2.getColorSpace()
111                    && lgp1.getTransform().equals(lgp2.getTransform());
112        } else if (p1 instanceof RadialGradientPaint 
113                && p2 instanceof RadialGradientPaint) {
114            RadialGradientPaint rgp1 = (RadialGradientPaint) p1;
115            RadialGradientPaint rgp2 = (RadialGradientPaint) p2;
116            return rgp1.getCenterPoint().equals(rgp2.getCenterPoint())
117                    && rgp1.getRadius() == rgp2.getRadius() 
118                    && rgp1.getFocusPoint().equals(rgp2.getFocusPoint())
119                    && Arrays.equals(rgp1.getFractions(), rgp2.getFractions())
120                    && Arrays.equals(rgp1.getColors(), rgp2.getColors())
121                    && rgp1.getCycleMethod() == rgp2.getCycleMethod()
122                    && rgp1.getColorSpace() == rgp2.getColorSpace()
123                    && rgp1.getTransform().equals(rgp2.getTransform());
124        } else {
125            return p1.equals(p2);
126        }
127    }
128
129    /**
130     * Converts a color into a string. If the color is equal to one of the
131     * defined constant colors, that name is returned instead. Otherwise the
132     * color is returned as hex-string.
133     *
134     * @param c the color.
135     * @return the string for this color.
136     */
137    public static String colorToString (final Color c) {
138        try {
139            final Field[] fields = Color.class.getFields();
140            for (int i = 0; i < fields.length; i++) {
141                final Field f = fields[i];
142                if (Modifier.isPublic(f.getModifiers())
143                        && Modifier.isFinal(f.getModifiers())
144                        && Modifier.isStatic(f.getModifiers())) {
145                    final String name = f.getName();
146                    final Object oColor = f.get(null);
147                    if (oColor instanceof Color) {
148                        if (c.equals(oColor)) {
149                            return name;
150                        }
151                    }
152                }
153            }
154        } catch (Exception e) {
155            //
156        }
157
158        // no defined constant color, so this must be a user defined color
159        final String color = Integer.toHexString(c.getRGB() & 0x00ffffff);
160        final StringBuffer retval = new StringBuffer(7);
161        retval.append("#");
162
163        final int fillUp = 6 - color.length();
164        for (int i = 0; i < fillUp; i++) {
165            retval.append("0");
166        }
167
168        retval.append(color);
169        return retval.toString();
170    }
171
172    /**
173     * Converts a given string into a color.
174     *
175     * @param value the string, either a name or a hex-string.
176     * @return the color.
177     */
178    public static Color stringToColor(String value) {
179        if (value == null) {
180            return Color.black;
181        }
182        try {
183            // get color by hex or octal value
184            return Color.decode(value);
185        } catch (NumberFormatException nfe) {
186            // if we can't decode lets try to get it by name
187            try {
188                // try to get a color by name using reflection
189                final Field f = Color.class.getField(value);
190                return (Color) f.get(null);
191            } catch (Exception ce) {
192                Log.info("No such Color : " + value);
193                // if we can't get any color return black
194                return Color.black;
195            }
196        }
197    }
198}