blob: 0c65bf0e713fb3c94b5d0b8fa3afedfbb7cd0d3d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.bpel.common.ui;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
/**
* General color utilities.
*/
public final class ColorUtils {
/**
* Gets a different color shade by changing its brightness
* with the provided variation.
*/
public static Color getShade(Color original, float brightnessVariation, Display display) {
brightnessVariation = isInvertedColorScheme() ? -brightnessVariation : brightnessVariation;
return new Color(display, getShadeRGB(original.getRGB(), brightnessVariation));
}
/**
* Gets a different color shade by changing its brightness
* with the provided variation.
*/
public static RGB getShadeRGB(RGB original, float brightnessVariation) {
// System.out.println("started " + original);
brightnessVariation = isInvertedColorScheme() ? -brightnessVariation : brightnessVariation;
float[] hsb = RGBtoHSB(original.red, original.green, original.blue, null);
hsb[2] += brightnessVariation;
int rgb = HSBtoRGB(hsb[0], hsb[1], hsb[2]);
// System.out.println(new RGB(getRed(rgb), getGreen(rgb), getBlue(rgb)));
return new RGB(getRed(rgb), getGreen(rgb), getBlue(rgb));
}
/**
* Returns an array of gradient colors from source to destination.
* The source and destination colors are not included in the array.
*/
public static Color[] getColorShades(Color source, Color destination, int n, Display display) {
float interval = getBrightnessInterval(source.getRGB(), destination.getRGB());
interval = interval / (n+2);
Color[] result = new Color[n];
Color base = source;
for (int i = 0; i < result.length; i++) {
result[i] = getShade(base, interval, display);
base = result[i];
}
return result;
}
/**
* Returns an array of gradient colors from source to destination.
* The source and destination colors are not included in the array.
*/
public static float getBrightnessInterval(RGB source, RGB destination) {
float[] sourceHSB = RGBtoHSB(source.red, source.green, source.blue, null);
float[] destinationHSB = RGBtoHSB(destination.red, destination.green, destination.blue, null);
return (destinationHSB[2] - sourceHSB[2]);
}
/**
* Returns an array of gradient colors from source to middle and from middle to destination.
* The middle color is included but the source and destination are not.
*/
public static Color[] getColorShades(Color source, Color middle, Color destination, int n, Display display) {
Color[] result = new Color[n+1];
Color[] temp = getColorShades(source, middle, (n/2), display);
System.arraycopy(temp, 0, result, 0, temp.length);
int pos = temp.length;
result[pos] = new Color(display, middle.getRGB());
temp = getColorShades(middle, destination, (n - temp.length), display);
System.arraycopy(temp, 0, result, (pos+1), temp.length);
return result;
}
/**
* Takes the source color and calculates the brightness interval with each
* color of the shades array. Then creates a new color array based on the
* destination color and the brightness intervals.
*/
public static RGB[] getColorShades(RGB source, RGB[] shades, RGB destination) {
RGB[] result = new RGB[shades.length];
for (int i = 0; i < shades.length; i++) {
RGB shade = shades[i];
float interval = getBrightnessInterval(source, shade);
result[i] = getShadeRGB(destination, interval);
}
return result;
}
/**
* Converts the specified HSB values to a RBG value.
*
* @version initial
*
* @param hue the hue component
* @param saturation the saturation component
* @param brightness the brightness component
*
* @return an <code>int</code> which is the converted RGB value
*/
public static int HSBtoRGB(float hue, float saturation, float brightness) {
float s = saturation;
float v = brightness;
int x = Math.round(v * 255);
if (s == 0) {
return 0xff000000 | (x << 16) | (x << 8) | x;
} else {
float h;
if (hue == 1.0f)
h = 0f;
else
h = (hue - (float)Math.floor(hue)) * 6.0f;
int i = (int)Math.floor(h);
float f = h - i;
int p = Math.round(255 * (v * (1 - s)));
int q = Math.round(255 * (v * (1 - (s * f))));
int t = Math.round(255 * (v * (1 - (s * (1 - f)))));
switch(i){
case 0: return 0xff000000 | (x << 16) | (t << 8) | p;
case 1: return 0xff000000 | (q << 16) | (x << 8) | p;
case 2: return 0xff000000 | (p << 16) | (x << 8) | t;
case 3: return 0xff000000 | (p << 16) | (q << 8) | x;
case 4: return 0xff000000 | (t << 16) | (p << 8) | x;
case 5: return 0xff000000 | (x << 16) | (p << 8) | q;
default: return 0;
}
}
}
/**
* Fill and return the specified array with the specified RGB values
* converted to HSB. Create, fill and return a new array if <code>null</code>
* is passed in.
* <p>
* Color components must be in the range (0 - 255).
*
* @version initial
*
* @param red the red component
* @param green the green component
* @param blue the blue component
* @param hsb the return value or <code>null</code>
*
* @return an <code>float[]</code> containing the converted HSB values
*
* @throws IllegalArgumentException if any of the components are invalid
*/
public static float[] RGBtoHSB(int red, int green, int blue, float hsb[]) {
if ((red < 0 || red > 255) ||
(green < 0 || green > 255) ||
(blue < 0 || blue > 255))
throw new IllegalArgumentException();
float r = red / 255f;
float g = green / 255f;
float b = blue / 255f;
float h = 0; // hue
float s; // saturation
float v; // brightnees
float max = Math.max(r, Math.max(g, b));
float min = Math.min(r, Math.min(g, b));
// Calculate brightness
v = max;
// Calculate saturation
if (max != 0)
s = (max - min)/max;
else
s = 0;
// Calculate hue
if (s != 0) {
float delta = max - min;
if (r == max)
h = (g - b)/delta;
else if (g == max)
h = 2 + (b - r)/delta;
else if (b == max)
h = 4 + (r - g)/delta;
h = h * 60f;
if (h < 0)
h = h + 360f;
h /= 360f;
}
// Fill return value
if (hsb == null)
return new float[]{h, s, v};
else {
hsb[0] = h;
hsb[1] = s;
hsb[2] = v;
return hsb;
}
}
/**
* Answers the blue component of the receiver.
*
* @version initial
*
* @return an <code>int</code> which is the blue component of the receiver
* in the range (0 - 255)
*
*/
private static final int getBlue(int rgb) {
return rgb & 0xff;
}
/**
* Answers the green component of the receiver.
*
* @version initial
*
* @return an <code>int</code> which is the green component of the receiver
* in the range (0 - 255)
*/
private static final int getGreen(int rgb) {
return (rgb & 0xff00) >> 8;
}
/**
* Answers the red component of the receiver.
*
* @version initial
*
* @return an <code>int</code> which is the red component of the receiver
* in the range (0 - 255)
*/
private static final int getRed(int rgb) {
return (rgb & 0xff0000) >> 16;
}
/**
* Replaces the given color in the image data.
*/
public static void replaceColor(ImageData data, RGB from, RGB to) {
for (int x = 0; x < data.width; x++) {
for (int y = 0; y < data.height; y++) {
int pixel = data.getPixel(x, y);
RGB rgb = data.palette.getRGB(pixel);
if (rgb.equals(from)) {
pixel = data.palette.getPixel(to);
}
data.setPixel(x, y, pixel);
}
}
}
/**
* scales the colors to be relative to the background and foreground colors (used to handle
* high contrast mode)
*
**/
public static Color getRelativeColor(Device device, int r, int g, int b) {
Color baseForeground = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
Color baseBackground = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
int fr = baseForeground.getRed();
int fg = baseForeground.getGreen();
int fb = baseForeground.getBlue();
int br = baseBackground.getRed();
int bg = baseBackground.getGreen();
int bb = baseBackground.getBlue();
int nr = (int) (fr + ((float)r * (br-fr) / 255));
int ng = (int) (fg + ((float)g * (bg-fg) / 255));
int nb = (int) (fb + ((float)b * (bb-fb) / 255));
// safety check, make sure all colors are in the correct range (in case we change the calculation above
nr = Math.max(0, nr);
nr = Math.min(255, nr);
ng = Math.max(0, ng);
ng = Math.min(255, ng);
nb = Math.max(0, nb);
nb = Math.min(255, nb);
return new Color(null, nr, ng, nb);
}
/**
* Scales the colors to be relative to the background and foreground colors (used to handle
* high contrast mode)
*/
public static RGB getRelativeRGB(int r, int g, int b) {
Color baseForeground = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
Color baseBackground = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
int fr = baseForeground.getRed();
int fg = baseForeground.getGreen();
int fb = baseForeground.getBlue();
int br = baseBackground.getRed();
int bg = baseBackground.getGreen();
int bb = baseBackground.getBlue();
int nr = (int) (fr + ((float)r * (br-fr) / 255));
int ng = (int) (fg + ((float)g * (bg-fg) / 255));
int nb = (int) (fb + ((float)b * (bb-fb) / 255));
// safety check, make sure all colors are in the correct range (in case we change the calculation above
nr = Math.max(0, nr);
nr = Math.min(255, nr);
ng = Math.max(0, ng);
ng = Math.min(255, ng);
nb = Math.max(0, nb);
nb = Math.min(255, nb);
return new RGB(nr, ng, nb);
}
public static Color getRelativeColor(Color c) {
Color cr = getRelativeColor(null, c.getRed(), c.getGreen(), c.getBlue());
c.dispose();
return cr;
}
public static Color getRelativeColorFromSystem(Color c) {
return getRelativeColor(null, c.getRed(), c.getGreen(), c.getBlue());
}
public static boolean isInvertedColorScheme() {
Color baseForeground = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
Color baseBackground = Display.getCurrent().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
// normally, the foreground color is dark, compare the sums to see which one is "lighter"
if ((baseForeground.getRed() + baseForeground.getBlue() + baseForeground.getGreen()) >
(baseBackground.getRed() + baseBackground.getBlue() + baseBackground.getGreen())) {
return true;
}
return false;
}
public static RGB getLightShade(RGB rgb, int numerator, int denominator) {
int light = 255 * numerator;
int red = (rgb.red + light) / denominator;
int green = (rgb.green + light) / denominator;
int blue = (rgb.blue + light) / denominator;
return new RGB(red, green, blue);
}
}