blob: 25fd23d81414542d82b6be01581f4c93915e7024 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2020 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:
* Junji MAEDA - initial API and implementation
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.visualization.internal.engines.lowvision.color;
import java.util.StringTokenizer;
import org.eclipse.actf.util.logging.DebugPrintUtil;
/*
* colors in CSS
* RGB(256)
*
* valid syntax
* #RRGGBB
* #RGB
* rgb(R,G,B)
* rgb(R%,G%,B%)
* pre-defined colors(16) (see ColorUtil.java)
*
* //2020-01
* hsl(h,s%,l%) *
* rgba/hsla -> try to calculate if a=1. if a!=1 then throws exception
*/
@SuppressWarnings("nls")
public class ColorCSS extends ColorIRGB {
private static final String DELIM = "/";
// default values
static final int TRANSPARENT_R = 0xff; // "transparent"
static final int TRANSPARENT_G = 0xff; // "transparent"
static final int TRANSPARENT_B = 0xff; // "transparent"
public static final int TRANSPARENT = ((TRANSPARENT_R & 0xff) << 16) | ((TRANSPARENT_G & 0xff) << 8)
| (TRANSPARENT_B & 0xff);
public static final int DEFAULT_BACKGROUND_COLOR_INT = TRANSPARENT;
public static final int DEFAULT_COLOR_INT = 0;
private static ColorIRGB parseHSL(String hsl) {
// assume (h, s%, l%) format
String target = hsl.replaceAll("[^0-9\\.,]", "");
// System.out.println(hsl + ":\t" + target);
StringTokenizer st = new StringTokenizer(target, ",", false);
double h, s, l, max, min;
double r, g, b;
int ri, gi, bi;
if (st.countTokens() == 3) {
try {
h = Float.parseFloat(st.nextToken());
s = Float.parseFloat(st.nextToken());
l = Float.parseFloat(st.nextToken());
// assume valid data
// TODO validation if needed
if (l >= 50) {
max = 2.55 * (l + (100 - l) * (s / 100));
min = 2.55 * (l - (100 - l) * (s / 100));
} else {
max = 2.55 * (l + l * (s / 100));
min = 2.55 * (l - l * (s / 100));
}
if (0 <= h && h < 60) {
r = max;
g = (h / 60) * (max - min) + min;
b = min;
} else if (60 <= h && h < 120) {
r = ((120 - h) / 60) * (max - min) + min;
g = max;
b = min;
} else if (120 <= h && h < 180) {
r = min;
g = max;
b = ((h - 120) / 60) * (max - min) + min;
} else if (180 <= h && h < 240) {
r = min;
g = ((240 - h) / 60) * (max - min) + min;
b = max;
} else if (240 <= h && h < 300) {
r = ((h - 240) / 60) * (max - min) + min;
g = min;
b = max;
} else if (300 <= h && h < 360) {
r = max;
g = min;
b = ((360 - h) / 60) * (max - min) + min;
} else {
// error
return null;
}
ri = (int) Math.round(r);
gi = (int) Math.round(g);
bi = (int) Math.round(b);
ColorIRGB ci = new ColorIRGB(ri, gi, bi);
return ci;
// System.out.println(target + ":\t" + ri + ", " + gi + ", " +
// bi);
} catch (Exception e) {
DebugPrintUtil.debugPrintStackTrace(e);
}
}
return null;
}
private String originalString = "";
private boolean hasAlpha = false;
public ColorCSS(String _s) throws ColorException {
this(_s, true);
}
public ColorCSS(String _s, boolean _check) throws ColorException {
_s = _s.replaceAll("\\p{Space}", "").toLowerCase();
if (!(_s.endsWith(DELIM))) {
originalString = _s;
} else {
originalString = _s.substring(0, _s.length() - 1);
}
if (originalString.startsWith("rgba") || originalString.startsWith("hsla")) {
hasAlpha = true;
// if alpha = 1 then try to convert value into RGB
if (originalString.endsWith(",1)")) {
originalString = originalString.substring(0, 3)
+ originalString.substring(4, originalString.length() - 3) + ")";
} else {
throw new ColorException(ColorException.ALPHA_EXISTS);
}
}
// foreground color
if (originalString.indexOf(DELIM) == -1) {
if (originalString.startsWith("hsl")) {
ColorIRGB ci = parseHSL(originalString);
if (ci != null) {
R = ci.getR();
G = ci.getG();
B = ci.getB();
}
} else {
try {
ColorIRGB ci = new ColorIRGB(originalString);
R = ci.getR();
G = ci.getG();
B = ci.getB();
} catch (ColorException e) {
if (hasAlpha) {
throw new ColorException(ColorException.ALPHA_EXISTS);
}
}
}
} else { // background-color -> need to consider ancestor
StringTokenizer st = new StringTokenizer(originalString.toLowerCase(), DELIM);
boolean success = false;
while (st.hasMoreTokens()) {
String tmpStr = st.nextToken();
if (!(tmpStr.equals("transparent"))) {
// ColorIRGB ci = interpret( tmpStr );
ColorIRGB ci = new ColorIRGB(tmpStr);
R = ci.getR();
G = ci.getG();
B = ci.getB();
success = true;
break;
}
}
if (!success) {
R = TRANSPARENT_R;
G = TRANSPARENT_G;
B = TRANSPARENT_B;
}
}
if (_check) {
rangeCheck();
} else {
rangeAdjust();
}
}
public ColorCSS() throws ColorException {
throw new ColorException("Constructor in wrong format.");
}
public ColorCSS(int _i) throws ColorException {
throw new ColorException("Constructor in wrong format.");
}
public ColorCSS(int _i1, int _i2, int _i3) throws ColorException {
throw new ColorException("Constructor in wrong format.");
}
public ColorCSS(int _i1, int _i2, int _i3, boolean _b) throws ColorException {
throw new ColorException("Constructor in wrong format.");
}
private void rangeCheck() throws ColorException {
if (R < 0 || R > 255) {
throw new ColorException("R is out of range: " + R + ", inputString = " + originalString);
}
if (G < 0 || G > 255) {
throw new ColorException("G is out of range: " + G + ", inputString = " + originalString);
}
if (B < 0 || B > 255) {
throw new ColorException("B is out of range: " + B + ", inputString = " + originalString);
}
}
private void rangeAdjust() {
if (R < 0)
R = 0;
else if (R > 255)
R = 255;
if (G < 0)
G = 0;
else if (G > 255)
G = 255;
if (B < 0)
B = 0;
else if (B > 255)
B = 255;
}
public String getOriginalString() {
return (originalString);
}
}