blob: d7ab3624e591d29ec1805b1b822add9e5817b4f9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
package org.apache.xmlgraphics.java2d.color;
import java.awt.Color;
/**
* Generic Color helper class.
* <p>
* This class supports parsing string values into color values and creating
* color values for strings. It provides a list of standard color names.
*/
public final class ColorUtil {
/**
* Private constructor since this is an utility class.
*/
private ColorUtil() {
}
/**
* Lightens up a color for groove, ridge, inset and outset border effects.
* @param col the color to lighten up
* @param factor factor by which to lighten up (negative values darken the color)
* @return the modified color
*/
public static Color lightenColor(Color col, float factor) {
// TODO: This function converts the color into the sRGB namespace.
// This should be avoided if possible.
float[] cols = new float[4];
cols = col.getRGBComponents(cols);
if (factor > 0) {
cols[0] += (1.0 - cols[0]) * factor;
cols[1] += (1.0 - cols[1]) * factor;
cols[2] += (1.0 - cols[2]) * factor;
} else {
cols[0] -= cols[0] * -factor;
cols[1] -= cols[1] * -factor;
cols[2] -= cols[2] * -factor;
}
return new Color(cols[0], cols[1], cols[2], cols[3]);
}
/**
* Indicates whether the color is a gray value.
* @param col the color
* @return true if it is a gray value
*/
public static boolean isGray(Color col) {
return (col.getRed() == col.getBlue() && col.getRed() == col.getGreen());
}
/**
* Creates an uncalibrated CMYK color with the given gray value.
* @param black the gray component (0 - 1)
* @return the CMYK color
*/
public static Color toCMYKGrayColor(float black) {
//Calculated color components
float[] cmyk = new float[] {0f, 0f, 0f, 1.0f - black};
//Create native color
return DeviceCMYKColorSpace.createCMYKColor(cmyk);
}
/**
* Converts an arbitrary {@link Color} to a plain sRGB color doing the conversion at the
* best possible conversion quality.
* @param col the original color
* @return the sRGB equivalent
*/
public static Color toSRGBColor(Color col) {
if (col.getColorSpace().isCS_sRGB()) {
return col; //Don't convert if already sRGB to avoid conversion differences
}
float[] comps = col.getColorComponents(null);
float[] srgb = col.getColorSpace().toRGB(comps);
comps = col.getComponents(null);
float alpha = comps[comps.length - 1];
return new Color(srgb[0], srgb[1], srgb[2], alpha);
}
/**
* Checks if two colors are the same color. This check is much more restrictive than
* {@link Color#equals(Object)} in that it doesn't only check if both colors result in the
* same sRGB value. For example, if two colors not of the same exact class are compared,
* they are treated as not the same.
* <p>
* Note: At the moment, this method only supports {@link Color} and
* {@link ColorWithAlternatives} only. Other subclasses of {@link Color} are checked only using
* the {@link Color#equals(Object)} method.
* @param col1 the first color
* @param col2 the second color
* @return true if both colors are the same color
*/
public static boolean isSameColor(Color col1, Color col2) {
//Check fallback sRGB values first, then go into details
if (!col1.equals(col2)) {
return false;
}
//Consider same-ness only between colors of the same class (not subclasses)
//but consider a ColorWithAlternatives without alternatives to be the same as a Color.
Class<?> cl1 = col1.getClass();
if (col1 instanceof ColorWithAlternatives
&& !((ColorWithAlternatives) col1).hasAlternativeColors()) {
cl1 = Color.class;
}
Class<?> cl2 = col2.getClass();
if (col2 instanceof ColorWithAlternatives
&& !((ColorWithAlternatives) col2).hasAlternativeColors()) {
cl2 = Color.class;
}
if (cl1 != cl2) {
return false;
}
//Check color space
if (!col1.getColorSpace().equals(col2.getColorSpace())) {
return false;
}
//Check native components
float[] comps1 = col1.getComponents(null);
float[] comps2 = col2.getComponents(null);
if (comps1.length != comps2.length) {
return false;
}
for (int i = 0, c = comps1.length; i < c; i++) {
if (comps1[i] != comps2[i]) {
return false;
}
}
//Compare alternative colors, order is relevant
if (col1 instanceof ColorWithAlternatives && col2 instanceof ColorWithAlternatives) {
ColorWithAlternatives ca1 = (ColorWithAlternatives) col1;
ColorWithAlternatives ca2 = (ColorWithAlternatives) col2;
return ca1.hasSameAlternativeColors(ca2);
}
return true;
}
}