1 package org.simantics.utils.ui.color;
3 import java.util.ArrayList;
4 import java.util.Collection;
7 import org.eclipse.swt.SWT;
8 import org.eclipse.swt.graphics.Color;
9 import org.eclipse.swt.graphics.GC;
10 import org.eclipse.swt.graphics.Image;
11 import org.eclipse.swt.widgets.Display;
13 public class ColorAlphaGradient extends ColorGradient {
15 List<Integer> alphaValues;
18 public ColorAlphaGradient() {
20 this.alphaValues = new ArrayList<>();
23 public ColorAlphaGradient(ColorAlphaGradient copyFrom) {
25 this.alphaValues = copyFrom.alphaValues;
28 public ColorAlphaGradient(ColorValue array[], int alphaArray[]) {
30 if (array.length != alphaArray.length)
31 throw new IllegalArgumentException("Array lenghts do not match.");
32 this.alphaValues = new ArrayList<>(alphaArray.length);
33 for (int a : alphaArray) {
38 public ColorAlphaGradient(ColorValue array[], int alphaArray[], int type) {
40 if (array.length != alphaArray.length)
41 throw new IllegalArgumentException("Array lenghts do not match.");
42 this.alphaValues = new ArrayList<>(alphaArray.length);
43 for (int a : alphaArray) {
48 public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues) {
50 if (values.size() != alphaValues.size())
51 throw new IllegalArgumentException("Array lenghts do not match.");
52 this.alphaValues = new ArrayList<>(alphaValues);
55 public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues, int type) {
57 if (values.size() != alphaValues.size())
58 throw new IllegalArgumentException("Array lenghts do not match.");
59 this.alphaValues = new ArrayList<>(alphaValues);
63 * Interpolates color in RGB space
68 private byte[] getRGBColor(double value) {
70 while (values.get(index).getValue() <= value && index < values.size()-1)
73 value -= values.get(index - 1).getValue();
74 value /= (values.get(index).getValue() - values.get(index - 1).getValue());
75 double valuei = 1.0 - value;
76 byte color[] = new byte[] {
77 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getR() + valuei * values.get(index - 1).getColor().getR())),
78 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getG() + valuei * values.get(index - 1).getColor().getG())),
79 (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getB() + valuei * values.get(index - 1).getColor().getB())),
80 (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index) + valuei * alphaValues.get(index - 1)))};
86 * Interpolates color in HSV space
91 private byte[] getHSVColor(double value) {
93 while (values.get(index).getValue() <= value && index < values.size()-1)
96 value -= values.get(index - 1).getValue();
97 value /= (values.get(index).getValue() - values.get(index - 1).getValue());
98 double valuei = 1.0 - value;
100 if (Float.isNaN(values.get(index).getColor().getH())) {
101 h = values.get(index-1).getColor().getH();
102 } else if (Float.isNaN(values.get(index-1).getColor().getH())) {
103 h = values.get(index).getColor().getH();
105 // selecting shortest direction between hues
106 float angle = values.get(index).getColor().getH() - values.get(index - 1).getColor().getH();
109 else if (angle < -180.f)
111 h = values.get(index - 1).getColor().getH() + value * angle;
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(),
118 value * values.get(index).getColor().getV() + valuei * values.get(index - 1).getColor().getV());
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)))};
127 * Returns gradient in array of bytes. Array is RGB order and int contains 3 * requested size of bytes.
130 * If gradient contains only one color array is filled with that color
133 * if gradient has no colors array is filled with white
135 * @param size number of pixels
136 * @return gradient in array of bytes
138 public byte[] getGradientArray(int size) {
139 byte array[] = new byte[size * 4];
140 if (values.size() > 1) {
141 for (int i = 0; i < size; i++) {
143 double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) i / (double) size;
146 color = getRGBColor(value);
148 color = getHSVColor(value);
149 array[index] = color[0];
150 array[index + 1] = color[1];
151 array[index + 2] = color[2];
152 array[index + 3] = color[3];
154 } else if (values.size() == 1) {
155 byte color[] = new byte[3];
156 color[0] = (byte)values.get(0).getColor().getR();
157 color[1] = (byte)values.get(0).getColor().getG();
158 color[2] = (byte)values.get(0).getColor().getB();
159 color[3] = (byte)(int)alphaValues.get(0);
160 for (int i = 0; i < size; i++) {
162 array[index] = color[0];
163 array[index + 1] = color[1];
164 array[index + 2] = color[2];
165 array[index + 3] = color[3];
168 for (int i = 0; i < size; i++) {
170 array[index] = (byte)255;
171 array[index + 1] = (byte)255;
172 array[index + 2] = (byte)255;
173 array[index + 3] = (byte)255;
181 * Returns gradient in image.
184 * If gradient contains only one color image is filled with that color
187 * if gradient has no colors image is filled with white
190 * Style must be set to <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>
192 * @param size number of pixels
193 * @return gradient in array of bytes
196 public Image getGradientImage(int width, int height, int style) {
197 Image image = new Image(Display.getCurrent(), width, height);
198 GC gc = new GC(image);
199 gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
200 gc.fillRectangle(0, 0, width, height);
201 if (values.size() > 1) {
202 if (SWT.HORIZONTAL == (style | SWT.HORIZONTAL)) {
203 for (int x = 0; x < width; x++) {
204 double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) x / (double) (width - 1);
207 byteColor = getRGBColor(value);
209 byteColor = getHSVColor(value);
210 Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);
211 gc.setForeground(color);
212 gc.drawLine(x, 0, x, height);
215 } else if (SWT.VERTICAL == (style | SWT.VERTICAL)){
216 for (int y = 0; y < height; y++) {
217 double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) y
218 / (double) (height - 1);
221 byteColor = getRGBColor(value);
223 byteColor = getHSVColor(value);
224 Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);
225 gc.setForeground(color);
226 gc.drawLine(0, y, width, y);
232 SWT.error(SWT.ERROR_INVALID_ARGUMENT);
234 } else if (values.size() == 1) {
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));
236 gc.setBackground(color);
237 gc.fillRectangle(0, 0, width, height);
240 gc.fillRectangle(0, 0, width, height);
247 public boolean equals(Object obj) {
248 if (super.equals(obj)) {
249 ColorAlphaGradient cg = (ColorAlphaGradient)obj;
250 return alphaValues.containsAll(cg.alphaValues);