]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorAlphaGradient.java
Merged changes from SVN
[simantics/platform.git] / bundles / org.simantics.utils.ui / src / org / simantics / utils / ui / color / ColorAlphaGradient.java
1 package org.simantics.utils.ui.color;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.List;\r
6 \r
7 import org.eclipse.swt.SWT;\r
8 import org.eclipse.swt.graphics.Color;\r
9 import org.eclipse.swt.graphics.GC;\r
10 import org.eclipse.swt.graphics.Image;\r
11 import org.eclipse.swt.widgets.Display;\r
12 \r
13 public class ColorAlphaGradient extends ColorGradient {\r
14         \r
15         List<Integer> alphaValues;\r
16         \r
17         \r
18         public ColorAlphaGradient() {\r
19                 super();\r
20                 this.alphaValues = new ArrayList<>();\r
21         }\r
22         \r
23         public ColorAlphaGradient(ColorAlphaGradient copyFrom) {\r
24                 super(copyFrom);\r
25                 this.alphaValues = copyFrom.alphaValues;\r
26     }\r
27         \r
28         public ColorAlphaGradient(ColorValue array[], int alphaArray[]) {\r
29                 super(array);\r
30                 if (array.length != alphaArray.length)\r
31                         throw new IllegalArgumentException("Array lenghts do not match.");\r
32                 this.alphaValues = new ArrayList<>(alphaArray.length);\r
33                 for (int a : alphaArray) {\r
34             alphaValues.add(a);\r
35         }\r
36         }\r
37         \r
38         public ColorAlphaGradient(ColorValue array[], int alphaArray[], int type) {\r
39                 super(array, type);\r
40                 if (array.length != alphaArray.length)\r
41                         throw new IllegalArgumentException("Array lenghts do not match.");\r
42                 this.alphaValues = new ArrayList<>(alphaArray.length);\r
43                 for (int a : alphaArray) {\r
44             alphaValues.add(a);\r
45         }\r
46         }\r
47         \r
48         public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues) {\r
49                 super(values);\r
50                 if (values.size() != alphaValues.size())\r
51                         throw new IllegalArgumentException("Array lenghts do not match.");\r
52                 this.alphaValues = new ArrayList<>(alphaValues);\r
53         }\r
54         \r
55         public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues, int type) {\r
56                 super(values, type);\r
57                 if (values.size() != alphaValues.size())\r
58                         throw new IllegalArgumentException("Array lenghts do not match.");\r
59                 this.alphaValues = new ArrayList<>(alphaValues);\r
60         }\r
61         \r
62          /**\r
63      * Interpolates color in RGB space\r
64      * \r
65      * @param value\r
66      * @return\r
67      */\r
68     private byte[] getRGBColor(double value) {\r
69         int index = 1;\r
70         while (values.get(index).getValue() <= value && index < values.size()-1)\r
71             index++;\r
72 \r
73         value -= values.get(index - 1).getValue();\r
74         value /= (values.get(index).getValue() - values.get(index - 1).getValue());\r
75         double valuei = 1.0 - value;\r
76         byte color[] = new byte[] {\r
77                 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getR() + valuei * values.get(index - 1).getColor().getR())),\r
78                 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getG() + valuei * values.get(index - 1).getColor().getG())),\r
79                 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getB() + valuei * values.get(index - 1).getColor().getB())),\r
80                 (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index)              + valuei * alphaValues.get(index - 1)))};\r
81         return color;\r
82 \r
83     }\r
84 \r
85     /**\r
86      * Interpolates color in HSV space\r
87      * \r
88      * @param value\r
89      * @return\r
90      */\r
91     private byte[] getHSVColor(double value) {\r
92         int index = 1;\r
93         while (values.get(index).getValue() <= value && index < values.size()-1)\r
94             index++;\r
95 \r
96         value -= values.get(index - 1).getValue();\r
97         value /= (values.get(index).getValue() - values.get(index - 1).getValue());\r
98         double valuei = 1.0 - value;\r
99         double h;\r
100         if (Float.isNaN(values.get(index).getColor().getH())) {\r
101             h = values.get(index-1).getColor().getH();\r
102         } else if (Float.isNaN(values.get(index-1).getColor().getH())) {\r
103             h = values.get(index).getColor().getH();\r
104         } else {\r
105             // selecting shortest direction between hues\r
106             float angle = values.get(index).getColor().getH() - values.get(index - 1).getColor().getH();\r
107             if (angle > 180.f)\r
108                 angle -= 360.f;\r
109             else if (angle < -180.f)\r
110                 angle += 360.f;\r
111             h = values.get(index - 1).getColor().getH() + value * angle;\r
112             if (h > 360.f)\r
113                 h -= 360.f;\r
114             else if (h < 0.f)\r
115                 h+= 360.f;\r
116         }\r
117         org.simantics.utils.ui.color.Color interpolated = new org.simantics.utils.ui.color.Color(h, value * values.get(index).getColor().getS() + valuei * values.get(index - 1).getColor().getS(),\r
118                 value * values.get(index).getColor().getV() + valuei * values.get(index - 1).getColor().getV());\r
119         byte color[] = new byte[] { (byte) interpolated.getR(), (byte) interpolated.getG(), (byte) interpolated.getB(), (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index)              + valuei * alphaValues.get(index - 1)))};\r
120 \r
121         return color;\r
122 \r
123     }\r
124 \r
125     /**\r
126      * <p>\r
127      * Returns gradient in array of bytes. Array is RGB order and int contains 3 * requested size of bytes.\r
128      * </p>\r
129      * <p>\r
130      * If gradient contains only one color array is filled with that color\r
131      * </p>\r
132      * <p>\r
133      * if gradient has no colors array is filled with white\r
134      * </p>\r
135      * @param size number of pixels\r
136      * @return gradient in array of bytes\r
137      */\r
138     public byte[] getGradientArray(int size) {\r
139         byte array[] = new byte[size * 4];\r
140         if (values.size() > 1) {\r
141             for (int i = 0; i < size; i++) {\r
142                 int index = i * 4;\r
143                 double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) i / (double) size;\r
144                 byte color[];\r
145                 if (type == RGB)\r
146                     color = getRGBColor(value);\r
147                 else\r
148                     color = getHSVColor(value);\r
149                 array[index] = color[0];\r
150                 array[index + 1] = color[1];\r
151                 array[index + 2] = color[2];\r
152                 array[index + 3] = color[3];\r
153             }\r
154         } else if (values.size() == 1) {\r
155             byte color[] = new byte[3];\r
156             color[0] = (byte)values.get(0).getColor().getR();\r
157             color[1] = (byte)values.get(0).getColor().getG();\r
158             color[2] = (byte)values.get(0).getColor().getB();\r
159             color[3] = (byte)(int)alphaValues.get(0);\r
160             for (int i = 0; i < size; i++) {\r
161                 int index = i * 3;\r
162                 array[index] = color[0];\r
163                 array[index + 1] = color[1];\r
164                 array[index + 2] = color[2];\r
165                 array[index + 3] = color[3];\r
166             }\r
167         } else {\r
168             for (int i = 0; i < size; i++) {\r
169                 int index = i * 4;\r
170                 array[index] = (byte)255;\r
171                 array[index + 1] = (byte)255;\r
172                 array[index + 2] = (byte)255;\r
173                 array[index + 3] = (byte)255;\r
174             }\r
175         }\r
176         return array;\r
177     }\r
178 \r
179     /**\r
180      * <p>\r
181      * Returns gradient in image.\r
182      * </p>\r
183      * <p>\r
184      * If gradient contains only one color image is filled with that color\r
185      * </p>\r
186      * <p>\r
187      * if gradient has no colors image is filled with white\r
188      * </p>\r
189      * <p>\r
190      * Style must be set to  <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>\r
191      * </p>\r
192      * @param size number of pixels\r
193      * @return gradient in array of bytes\r
194      */\r
195     \r
196     public Image getGradientImage(int width, int height, int style) {\r
197         Image image = new Image(Display.getCurrent(), width, height);\r
198         GC gc = new GC(image);\r
199         gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));\r
200         gc.fillRectangle(0, 0, width, height);\r
201         if (values.size() > 1) {\r
202             if (SWT.HORIZONTAL == (style | SWT.HORIZONTAL)) {\r
203                 for (int x = 0; x < width; x++) {\r
204                     double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) x / (double) (width - 1);\r
205                     byte byteColor[];\r
206                     if (type == RGB)\r
207                         byteColor = getRGBColor(value);\r
208                     else\r
209                         byteColor = getHSVColor(value);\r
210                     Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);\r
211                     gc.setForeground(color);\r
212                     gc.drawLine(x, 0, x, height);\r
213                     color.dispose();\r
214                 }\r
215             } else if (SWT.VERTICAL == (style | SWT.VERTICAL)){\r
216                 for (int y = 0; y < height; y++) {\r
217                     double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) y\r
218                             / (double) (height - 1);\r
219                     byte byteColor[];\r
220                     if (type == RGB)\r
221                         byteColor = getRGBColor(value);\r
222                     else\r
223                         byteColor = getHSVColor(value);\r
224                     Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);\r
225                     gc.setForeground(color);\r
226                     gc.drawLine(0, y, width, y);\r
227                     color.dispose();\r
228                 }\r
229             } else {\r
230                 gc.dispose();\r
231                 image.dispose();\r
232                 SWT.error(SWT.ERROR_INVALID_ARGUMENT);\r
233             }\r
234         } else if (values.size() == 1) {\r
235             Color color = new Color(Display.getCurrent(), values.get(0).getColor().getR(), values.get(0).getColor().getG(), values.get(0).getColor().getB(), alphaValues.get(0));      \r
236             gc.setBackground(color);\r
237             gc.fillRectangle(0, 0, width, height);\r
238             color.dispose();\r
239         } else {\r
240             gc.fillRectangle(0, 0, width, height);\r
241         }\r
242         gc.dispose();\r
243         return image;\r
244     }\r
245     \r
246     @Override\r
247     public boolean equals(Object obj) {\r
248         if (super.equals(obj)) {\r
249                 ColorAlphaGradient cg = (ColorAlphaGradient)obj;\r
250                 return alphaValues.containsAll(cg.alphaValues);\r
251         } else {\r
252                 return false;\r
253         }\r
254     }\r
255 \r
256 }\r