001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.ui.swingViewer.util;
033
034import java.awt.Color;
035import java.awt.GradientPaint;
036import java.awt.LinearGradientPaint;
037import java.awt.MultipleGradientPaint;
038import java.awt.Paint;
039import java.awt.RadialGradientPaint;
040
041import org.graphstream.ui.graphicGraph.stylesheet.Style;
042import org.graphstream.ui.graphicGraph.stylesheet.StyleConstants.FillMode;
043
044public class GradientFactory {
045        /**
046         * Generate a gradient in the given pixel area following the given style.
047         * This produces a gradient only if the style fill-mode is compatible.
048         * 
049         * @param x0
050         *            The left corner of the area.
051         * @param y0
052         *            The bottom corner of the area.
053         * @param width
054         *            The area width.
055         * @param height
056         *            The area height.
057         * @param style
058         *            The style.
059         * @return A gradient paint or null if the style does not specify a
060         *         gradient.
061         */
062        public static Paint gradientInArea(int x0, int y0, int width, int height,
063                        Style style) {
064                switch (style.getFillMode()) {
065                case GRADIENT_VERTICAL:
066                        return linearGradientFromStyle(x0, y0, x0, y0 + height, style);
067                case GRADIENT_HORIZONTAL:
068                        return linearGradientFromStyle(x0, y0, x0 + width, y0, style);
069                case GRADIENT_DIAGONAL1:
070                        return linearGradientFromStyle(x0, y0, x0 + width, y0 + height,
071                                        style);
072                case GRADIENT_DIAGONAL2:
073                        return linearGradientFromStyle(x0 + width, y0, x0, y0 + height,
074                                        style);
075                case GRADIENT_RADIAL:
076                        return radialGradientFromStyle(x0 + (width / 2), y0 + (height / 2),
077                                        width > height ? width / 2 : height / 2, style);
078                default:
079                        return null;
080                }
081        }
082
083        /**
084         * Generate a linear gradient between two given points corresponding to the
085         * given style.
086         * 
087         * @param x0
088         *            The start point abscissa.
089         * @param y0
090         *            The start point ordinate.
091         * @param x1
092         *            The end point abscissa.
093         * @param y1
094         *            The end point ordinate.
095         * @param style
096         *            The style.
097         * @return A paint for the gradient or null if the style specifies no
098         *         gradient (the fill mode is not a linear gradient or there is only
099         *         one fill colour).
100         */
101        public static Paint linearGradientFromStyle(float x0, float y0, float x1,
102                        float y1, Style style) {
103                Paint paint = null;
104
105                if (style.getFillColorCount() > 1) {
106                        switch (style.getFillMode()) {
107                        case GRADIENT_DIAGONAL1:
108                        case GRADIENT_DIAGONAL2:
109                        case GRADIENT_HORIZONTAL:
110                        case GRADIENT_VERTICAL:
111                                if (version16)
112                                        paint = new LinearGradientPaint(x0, y0, x1, y1,
113                                                        createFractions(style), createColors(style));
114                                else
115                                        paint = new GradientPaint(x0, y0, style.getFillColor(0),
116                                                        x1, y1, style.getFillColor(1));
117                                break;
118                        default:
119                                break;
120                        }
121                }
122
123                return paint;
124        }
125
126        public static Paint radialGradientFromStyle(float cx, float cy,
127                        float radius, Style style) {
128                return radialGradientFromStyle(cx, cy, radius, cx, cy, style);
129        }
130
131        /**
132         * Generate a radial gradient between whose center is at (cx,cy) with the
133         * given radius. The focus (fx,fy) is the start position of the gradient in
134         * the circle.
135         * 
136         * @param cx
137         *            The center point abscissa.
138         * @param cy
139         *            The center point ordinate.
140         * @param fx
141         *            The start point abscissa.
142         * @param fy
143         *            The start point ordinate.
144         * @param radius
145         *            The gradient radius.
146         * @param style
147         *            The style.
148         * @return A paint for the gradient or null if the style specifies no
149         *         gradient (the fill mode is not a radial gradient or there is only
150         *         one fill colour).
151         */
152        public static Paint radialGradientFromStyle(float cx, float cy,
153                        float radius, float fx, float fy, Style style) {
154                Paint paint = null;
155
156                if (version16) {
157                        if (style.getFillColorCount() > 1
158                                        && style.getFillMode() == FillMode.GRADIENT_RADIAL) {
159                                float fractions[] = createFractions(style);
160                                Color colors[] = createColors(style);
161                                paint = new RadialGradientPaint(cx, cy, radius, fx, fy,
162                                                fractions, colors,
163                                                MultipleGradientPaint.CycleMethod.REFLECT);
164                        }
165                }
166
167                return paint;
168        }
169
170        protected static float[] createFractions(Style style) {
171                int n = style.getFillColorCount();
172
173                if (n < predefFractions.length)
174                        return predefFractions[n];
175
176                float fractions[] = new float[n];
177                float div = 1f / (n - 1);
178
179                for (int i = 1; i < (n - 1); i++)
180                        fractions[i] = div * i;
181
182                fractions[0] = 0f;
183                fractions[n - 1] = 1f;
184
185                return fractions;
186        }
187
188        protected static Color[] createColors(Style style) {
189                int n = style.getFillColorCount();
190                Color colors[] = new Color[n];
191
192                for (int i = 0; i < n; i++)
193                        colors[i] = style.getFillColor(i);
194
195                return colors;
196        }
197
198        public static boolean version16 = false;
199        public static float[][] predefFractions = new float[11][];
200        public static float[] predefFractions2 = { 0f, 1f };
201        public static float[] predefFractions3 = { 0f, 0.5f, 1f };
202        public static float[] predefFractions4 = { 0f, 0.33f, 0.66f, 1f };
203        public static float[] predefFractions5 = { 0f, 0.25f, 0.5f, 0.75f, 1f };
204        public static float[] predefFractions6 = { 0f, 0.2f, 0.4f, 0.6f, 0.8f, 1f };
205        public static float[] predefFractions7 = { 0f, 0.1666f, 0.3333f, 0.4999f,
206                        0.6666f, 0.8333f, 1f };
207        public static float[] predefFractions8 = { 0f, 0.1428f, 0.2856f, 0.4284f,
208                        0.5712f, 0.7140f, 0.8568f, 1f };
209        public static float[] predefFractions9 = { 0f, 0.125f, 0.25f, 0.375f, 0.5f,
210                        0.625f, .75f, 0.875f, 1f };
211        public static float[] predefFractions10 = { 0f, 0.1111f, 0.2222f, 0.3333f,
212                        0.4444f, 0.5555f, 0.6666f, 0.7777f, 0.8888f, 1f };
213
214        static {
215                String version = System.getProperty("java.version");
216
217                if (version.startsWith("1.") && version.length() >= 3) {
218                        String v = version.substring(2, 3);
219                        int n = Integer.parseInt(v);
220
221                        if (n >= 6)
222                                version16 = true;
223                }
224
225                predefFractions[0] = null;
226                predefFractions[1] = null;
227                predefFractions[2] = predefFractions2;
228                predefFractions[3] = predefFractions3;
229                predefFractions[4] = predefFractions4;
230                predefFractions[5] = predefFractions5;
231                predefFractions[6] = predefFractions6;
232                predefFractions[7] = predefFractions7;
233                predefFractions[8] = predefFractions8;
234                predefFractions[9] = predefFractions9;
235                predefFractions[10] = predefFractions10;
236        }
237}