| /* ==================================================================== |
| 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. |
| ==================================================================== */ |
| package org.apache.poi.ss.usermodel; |
| |
| import java.util.Locale; |
| |
| import org.apache.poi.hssf.util.HSSFColor; |
| |
| /** |
| * Represents a XSSF-style color (based on either a |
| * {@link org.apache.poi.xssf.usermodel.XSSFColor} or a |
| * {@link org.apache.poi.hssf.record.common.ExtendedColor} |
| */ |
| public abstract class ExtendedColor implements Color { |
| protected void setColor(java.awt.Color clr) { |
| setRGB(new byte[]{(byte)clr.getRed(), (byte)clr.getGreen(), (byte)clr.getBlue()}); |
| } |
| |
| /** |
| * A boolean value indicating the color is automatic |
| */ |
| public abstract boolean isAuto(); |
| |
| /** |
| * A boolean value indicating the color is indexed |
| */ |
| public abstract boolean isIndexed(); |
| |
| /** |
| * A boolean value indicating the color is RGB / ARGB |
| */ |
| public abstract boolean isRGB(); |
| |
| /** |
| * A boolean value indicating the color is from a Theme |
| */ |
| public abstract boolean isThemed(); |
| |
| /** |
| * Indexed Color value, if {@link #isIndexed()} is true |
| */ |
| public abstract short getIndex(); |
| |
| /** |
| * Index of Theme color, if {@link #isThemed()} is true |
| */ |
| public abstract int getTheme(); |
| |
| /** |
| * Standard Red Green Blue ctColor value (RGB). |
| * If there was an A (Alpha) value, it will be stripped. |
| */ |
| public abstract byte[] getRGB(); |
| /** |
| * Standard Alpha Red Green Blue ctColor value (ARGB). |
| */ |
| public abstract byte[] getARGB(); |
| |
| /** |
| * RGB or ARGB or null |
| */ |
| protected abstract byte[] getStoredRBG(); |
| |
| /** |
| * Sets the Red Green Blue or Alpha Red Green Blue |
| */ |
| public abstract void setRGB(byte[] rgb); |
| |
| protected byte[] getRGBOrARGB() { |
| if (isIndexed() && getIndex() > 0) { |
| int indexNum = getIndex(); |
| HSSFColor indexed = HSSFColor.getIndexHash().get(indexNum); |
| if (indexed != null) { |
| byte[] rgb = new byte[3]; |
| rgb[0] = (byte) indexed.getTriplet()[0]; |
| rgb[1] = (byte) indexed.getTriplet()[1]; |
| rgb[2] = (byte) indexed.getTriplet()[2]; |
| return rgb; |
| } |
| } |
| |
| // Grab the colour |
| return getStoredRBG(); |
| } |
| |
| /** |
| * Standard Red Green Blue ctColor value (RGB) with applied tint. |
| * Alpha values are ignored. |
| */ |
| public byte[] getRGBWithTint() { |
| byte[] rgb = getStoredRBG(); |
| if (rgb != null) { |
| if(rgb.length == 4) { |
| byte[] tmp = new byte[3]; |
| System.arraycopy(rgb, 1, tmp, 0, 3); |
| rgb = tmp; |
| } |
| double tint = getTint(); |
| for (int i = 0; i < rgb.length; i++){ |
| rgb[i] = applyTint(rgb[i] & 0xFF, tint); |
| } |
| } |
| return rgb; |
| } |
| |
| /** |
| * Return the ARGB value in hex format, eg FF00FF00. |
| * Works for both regular and indexed colours. |
| */ |
| public String getARGBHex() { |
| byte[] rgb = getARGB(); |
| if(rgb == null) { |
| return null; |
| } |
| |
| StringBuilder sb = new StringBuilder(); |
| for(byte c : rgb) { |
| int i = c & 0xff; |
| String cs = Integer.toHexString(i); |
| if(cs.length() == 1) { |
| sb.append('0'); |
| } |
| sb.append(cs); |
| } |
| return sb.toString().toUpperCase(Locale.ROOT); |
| } |
| |
| /** |
| * Sets the ARGB value from hex format, eg FF0077FF. |
| * Only works for regular (non-indexed) colours |
| */ |
| public void setARGBHex(String argb) { |
| if (argb.length() == 6 || argb.length() == 8) { |
| byte[] rgb = new byte[argb.length()/2]; |
| for (int i=0; i<rgb.length; i++) { |
| String part = argb.substring(i*2,(i+1)*2); |
| rgb[i] = (byte)Integer.parseInt(part, 16); |
| } |
| setRGB(rgb); |
| } else { |
| throw new IllegalArgumentException("Must be of the form 112233 or FFEEDDCC"); |
| } |
| } |
| |
| private static byte applyTint(int lum, double tint){ |
| if(tint > 0){ |
| return (byte)(lum * (1.0-tint) + (255 - 255 * (1.0-tint))); |
| } else if (tint < 0){ |
| return (byte)(lum*(1+tint)); |
| } else { |
| return (byte)lum; |
| } |
| } |
| |
| /** |
| * Specifies the tint value applied to the ctColor. |
| * |
| * <p> |
| * If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final |
| * ctColor applied. |
| * </p> |
| * <p> |
| * The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and |
| * 1.0 means 100% lighten. Also, 0.0 means no change. |
| * </p> |
| * <p> |
| * In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where |
| * HLSMAX is currently 255. |
| * </p> |
| * Here are some examples of how to apply tint to ctColor: |
| * <blockquote> |
| * <pre> |
| * If (tint < 0) |
| * Lum' = Lum * (1.0 + tint) |
| * |
| * For example: Lum = 200; tint = -0.5; Darken 50% |
| * Lum' = 200 * (0.5) => 100 |
| * For example: Lum = 200; tint = -1.0; Darken 100% (make black) |
| * Lum' = 200 * (1.0-1.0) => 0 |
| * If (tint > 0) |
| * Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint)) |
| * For example: Lum = 100; tint = 0.75; Lighten 75% |
| * |
| * Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75)) |
| * = 100 * .25 + (255 - 255 * .25) |
| * = 25 + (255 - 63) = 25 + 192 = 217 |
| * For example: Lum = 100; tint = 1.0; Lighten 100% (make white) |
| * Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1)) |
| * = 100 * 0 + (255 - 255 * 0) |
| * = 0 + (255 - 0) = 255 |
| * </pre> |
| * </blockquote> |
| * |
| * @return the tint value |
| */ |
| public abstract double getTint(); |
| |
| /** |
| * Specifies the tint value applied to the ctColor. |
| * |
| * <p> |
| * If tint is supplied, then it is applied to the RGB value of the ctColor to determine the final |
| * ctColor applied. |
| * </p> |
| * <p> |
| * The tint value is stored as a double from -1.0 .. 1.0, where -1.0 means 100% darken and |
| * 1.0 means 100% lighten. Also, 0.0 means no change. |
| * </p> |
| * <p> |
| * In loading the RGB value, it is converted to HLS where HLS values are (0..HLSMAX), where |
| * HLSMAX is currently 255. |
| * </p> |
| * Here are some examples of how to apply tint to ctColor: |
| * <blockquote> |
| * <pre> |
| * If (tint < 0) |
| * Lum' = Lum * (1.0 + tint) |
| * |
| * For example: Lum = 200; tint = -0.5; Darken 50% |
| * Lum' = 200 * (0.5) => 100 |
| * For example: Lum = 200; tint = -1.0; Darken 100% (make black) |
| * Lum' = 200 * (1.0-1.0) => 0 |
| * If (tint > 0) |
| * Lum' = Lum * (1.0-tint) + (HLSMAX - HLSMAX * (1.0-tint)) |
| * For example: Lum = 100; tint = 0.75; Lighten 75% |
| * |
| * Lum' = 100 * (1-.75) + (HLSMAX - HLSMAX*(1-.75)) |
| * = 100 * .25 + (255 - 255 * .25) |
| * = 25 + (255 - 63) = 25 + 192 = 217 |
| * For example: Lum = 100; tint = 1.0; Lighten 100% (make white) |
| * Lum' = 100 * (1-1) + (HLSMAX - HLSMAX*(1-1)) |
| * = 100 * 0 + (255 - 255 * 0) |
| * = 0 + (255 - 0) = 255 |
| * </pre> |
| * </blockquote> |
| * |
| * @param tint the tint value |
| */ |
| public abstract void setTint(double tint); |
| } |