]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorAlphaGradient.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/color/ColorAlphaGradient.java
new file mode 100644 (file)
index 0000000..05635df
--- /dev/null
@@ -0,0 +1,256 @@
+package org.simantics.utils.ui.color;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.widgets.Display;\r
+\r
+public class ColorAlphaGradient extends ColorGradient {\r
+       \r
+       List<Integer> alphaValues;\r
+       \r
+       \r
+       public ColorAlphaGradient() {\r
+               super();\r
+               this.alphaValues = new ArrayList<>();\r
+       }\r
+       \r
+       public ColorAlphaGradient(ColorAlphaGradient copyFrom) {\r
+               super(copyFrom);\r
+               this.alphaValues = copyFrom.alphaValues;\r
+    }\r
+       \r
+       public ColorAlphaGradient(ColorValue array[], int alphaArray[]) {\r
+               super(array);\r
+               if (array.length != alphaArray.length)\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaArray.length);\r
+               for (int a : alphaArray) {\r
+            alphaValues.add(a);\r
+        }\r
+       }\r
+       \r
+       public ColorAlphaGradient(ColorValue array[], int alphaArray[], int type) {\r
+               super(array, type);\r
+               if (array.length != alphaArray.length)\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaArray.length);\r
+               for (int a : alphaArray) {\r
+            alphaValues.add(a);\r
+        }\r
+       }\r
+       \r
+       public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues) {\r
+               super(values);\r
+               if (values.size() != alphaValues.size())\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaValues);\r
+       }\r
+       \r
+       public ColorAlphaGradient(Collection<ColorValue> values, Collection<Integer> alphaValues, int type) {\r
+               super(values, type);\r
+               if (values.size() != alphaValues.size())\r
+                       throw new IllegalArgumentException("Array lenghts do not match.");\r
+               this.alphaValues = new ArrayList<>(alphaValues);\r
+       }\r
+       \r
+        /**\r
+     * Interpolates color in RGB space\r
+     * \r
+     * @param value\r
+     * @return\r
+     */\r
+    private byte[] getRGBColor(double value) {\r
+        int index = 1;\r
+        while (values.get(index).getValue() <= value && index < values.size()-1)\r
+            index++;\r
+\r
+        value -= values.get(index - 1).getValue();\r
+        value /= (values.get(index).getValue() - values.get(index - 1).getValue());\r
+        double valuei = 1.0 - value;\r
+        byte color[] = new byte[] {\r
+                (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getR() + valuei * values.get(index - 1).getColor().getR())),\r
+                (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getG() + valuei * values.get(index - 1).getColor().getG())),\r
+                (byte) Math.min(255.0, Math.floor(value * values.get(index).getColor().getB() + valuei * values.get(index - 1).getColor().getB())),\r
+                (byte) Math.min(255.0, Math.floor(value * alphaValues.get(index)              + valuei * alphaValues.get(index - 1)))};\r
+        return color;\r
+\r
+    }\r
+\r
+    /**\r
+     * Interpolates color in HSV space\r
+     * \r
+     * @param value\r
+     * @return\r
+     */\r
+    private byte[] getHSVColor(double value) {\r
+        int index = 1;\r
+        while (values.get(index).getValue() <= value && index < values.size()-1)\r
+            index++;\r
+\r
+        value -= values.get(index - 1).getValue();\r
+        value /= (values.get(index).getValue() - values.get(index - 1).getValue());\r
+        double valuei = 1.0 - value;\r
+        double h;\r
+        if (Float.isNaN(values.get(index).getColor().getH())) {\r
+            h = values.get(index-1).getColor().getH();\r
+        } else if (Float.isNaN(values.get(index-1).getColor().getH())) {\r
+            h = values.get(index).getColor().getH();\r
+        } else {\r
+            // selecting shortest direction between hues\r
+            float angle = values.get(index).getColor().getH() - values.get(index - 1).getColor().getH();\r
+            if (angle > 180.f)\r
+                angle -= 360.f;\r
+            else if (angle < -180.f)\r
+                angle += 360.f;\r
+            h = values.get(index - 1).getColor().getH() + value * angle;\r
+            if (h > 360.f)\r
+                h -= 360.f;\r
+            else if (h < 0.f)\r
+                h+= 360.f;\r
+        }\r
+        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
+                value * values.get(index).getColor().getV() + valuei * values.get(index - 1).getColor().getV());\r
+        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
+\r
+        return color;\r
+\r
+    }\r
+\r
+    /**\r
+     * <p>\r
+     * Returns gradient in array of bytes. Array is RGB order and int contains 3 * requested size of bytes.\r
+     * </p>\r
+     * <p>\r
+     * If gradient contains only one color array is filled with that color\r
+     * </p>\r
+     * <p>\r
+     * if gradient has no colors array is filled with white\r
+     * </p>\r
+     * @param size number of pixels\r
+     * @return gradient in array of bytes\r
+     */\r
+    public byte[] getGradientArray(int size) {\r
+        byte array[] = new byte[size * 4];\r
+        if (values.size() > 1) {\r
+            for (int i = 0; i < size; i++) {\r
+                int index = i * 4;\r
+                double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) i / (double) size;\r
+                byte color[];\r
+                if (type == RGB)\r
+                    color = getRGBColor(value);\r
+                else\r
+                    color = getHSVColor(value);\r
+                array[index] = color[0];\r
+                array[index + 1] = color[1];\r
+                array[index + 2] = color[2];\r
+                array[index + 3] = color[3];\r
+            }\r
+        } else if (values.size() == 1) {\r
+            byte color[] = new byte[3];\r
+            color[0] = (byte)values.get(0).getColor().getR();\r
+            color[1] = (byte)values.get(0).getColor().getG();\r
+            color[2] = (byte)values.get(0).getColor().getB();\r
+            color[3] = (byte)(int)alphaValues.get(0);\r
+            for (int i = 0; i < size; i++) {\r
+                int index = i * 3;\r
+                array[index] = color[0];\r
+                array[index + 1] = color[1];\r
+                array[index + 2] = color[2];\r
+                array[index + 3] = color[3];\r
+            }\r
+        } else {\r
+            for (int i = 0; i < size; i++) {\r
+                int index = i * 4;\r
+                array[index] = (byte)255;\r
+                array[index + 1] = (byte)255;\r
+                array[index + 2] = (byte)255;\r
+                array[index + 3] = (byte)255;\r
+            }\r
+        }\r
+        return array;\r
+    }\r
+\r
+    /**\r
+     * <p>\r
+     * Returns gradient in image.\r
+     * </p>\r
+     * <p>\r
+     * If gradient contains only one color image is filled with that color\r
+     * </p>\r
+     * <p>\r
+     * if gradient has no colors image is filled with white\r
+     * </p>\r
+     * <p>\r
+     * Style must be set to  <code>SWT.HORIZONTAL</code> or <code>SWT.VERTICAL</code>\r
+     * </p>\r
+     * @param size number of pixels\r
+     * @return gradient in array of bytes\r
+     */\r
+    \r
+    public Image getGradientImage(int width, int height, int style) {\r
+        Image image = new Image(Display.getCurrent(), width, height);\r
+        GC gc = new GC(image);\r
+        gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));\r
+        gc.fillRectangle(0, 0, width, height);\r
+        if (values.size() > 1) {\r
+            if (SWT.HORIZONTAL == (style | SWT.HORIZONTAL)) {\r
+                for (int x = 0; x < width; x++) {\r
+                    double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) x / (double) (width - 1);\r
+                    byte byteColor[];\r
+                    if (type == RGB)\r
+                        byteColor = getRGBColor(value);\r
+                    else\r
+                        byteColor = getHSVColor(value);\r
+                    Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);\r
+                    gc.setForeground(color);\r
+                    gc.drawLine(x, 0, x, height);\r
+                    color.dispose();\r
+                }\r
+            } else if (SWT.VERTICAL == (style | SWT.VERTICAL)){\r
+                for (int y = 0; y < height; y++) {\r
+                    double value = values.get(0).getValue() + (values.get(values.size() - 1).getValue() - values.get(0).getValue()) * (double) y\r
+                            / (double) (height - 1);\r
+                    byte byteColor[];\r
+                    if (type == RGB)\r
+                        byteColor = getRGBColor(value);\r
+                    else\r
+                        byteColor = getHSVColor(value);\r
+                    Color color = new Color(Display.getCurrent(), byteColor[0] & 0xff, byteColor[1] & 0xff, byteColor[2] & 0xff, byteColor[3] & 0xff);\r
+                    gc.setForeground(color);\r
+                    gc.drawLine(0, y, width, y);\r
+                    color.dispose();\r
+                }\r
+            } else {\r
+                gc.dispose();\r
+                image.dispose();\r
+                SWT.error(SWT.ERROR_INVALID_ARGUMENT);\r
+            }\r
+        } else if (values.size() == 1) {\r
+            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
+            gc.setBackground(color);\r
+            gc.fillRectangle(0, 0, width, height);\r
+            color.dispose();\r
+        } else {\r
+            gc.fillRectangle(0, 0, width, height);\r
+        }\r
+        gc.dispose();\r
+        return image;\r
+    }\r
+    \r
+    @Override\r
+    public boolean equals(Object obj) {\r
+       if (super.equals(obj)) {\r
+               ColorAlphaGradient cg = (ColorAlphaGradient)obj;\r
+               return alphaValues.containsAll(cg.alphaValues);\r
+       } else {\r
+               return false;\r
+       }\r
+    }\r
+\r
+}\r