1 package org.simantics.utils.ui.color;
\r
3 import java.util.ArrayList;
\r
4 import java.util.Collection;
\r
5 import java.util.List;
\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
13 public class ColorAlphaGradient extends ColorGradient {
\r
15 List<Integer> alphaValues;
\r
18 public ColorAlphaGradient() {
\r
20 this.alphaValues = new ArrayList<>();
\r
23 public ColorAlphaGradient(ColorAlphaGradient copyFrom) {
\r
25 this.alphaValues = copyFrom.alphaValues;
\r
28 public ColorAlphaGradient(ColorValue array[], int alphaArray[]) {
\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
38 public ColorAlphaGradient(ColorValue array[], int alphaArray[], int 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
48 public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues) {
\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
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
63 * Interpolates color in RGB space
\r
68 private byte[] getRGBColor(double value) {
\r
70 while (values.get(index).getValue() <= value && index < values.size()-1)
\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
86 * Interpolates color in HSV space
\r
91 private byte[] getHSVColor(double value) {
\r
93 while (values.get(index).getValue() <= value && index < values.size()-1)
\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
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
105 // selecting shortest direction between hues
\r
106 float angle = values.get(index).getColor().getH() - values.get(index - 1).getColor().getH();
\r
109 else if (angle < -180.f)
\r
111 h = values.get(index - 1).getColor().getH() + value * angle;
\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
127 * Returns gradient in array of bytes. Array is RGB order and int contains 3 * requested size of bytes.
\r
130 * If gradient contains only one color array is filled with that color
\r
133 * if gradient has no colors array is filled with white
\r
135 * @param size number of pixels
\r
136 * @return gradient in array of bytes
\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
143 double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) i / (double) size;
\r
146 color = getRGBColor(value);
\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
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
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
168 for (int i = 0; i < size; i++) {
\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
181 * Returns gradient in image.
\r
184 * If gradient contains only one color image is filled with that color
\r
187 * if gradient has no colors image is filled with white
\r
190 * Style must be set to <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>
\r
192 * @param size number of pixels
\r
193 * @return gradient in array of bytes
\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
207 byteColor = getRGBColor(value);
\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
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
221 byteColor = getRGBColor(value);
\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
232 SWT.error(SWT.ERROR_INVALID_ARGUMENT);
\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
240 gc.fillRectangle(0, 0, width, height);
\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